[{"data":1,"prerenderedAt":21},["ShallowReactive",2],{"blog-detail:uniswap-v4-a-deep-dive-into-its-security-landscape":3},{"category":4,"article":5},null,{"slug":6,"category":7,"categoryLabel":8,"subcategoryLabel":9,"authorName":10,"title":11,"excerpt":12,"contentHtml":13,"coverUrl":14,"seoTitle":11,"seoDescription":15,"seoImageUrl":14,"publishedAt":16,"updatedAt":17,"readTime":18,"cover":14,"hasCover":19,"coverAlt":20},"uniswap-v4-a-deep-dive-into-its-security-landscape","research","Research","Incident Analysis","ScaleBit","Uniswap V4：Analyzing the Security Landscape Beneath the Surface","In the fast-paced world of decentralized finance (DeFi), exchanges are pivotal in enabling the smooth transfer of assets. Uniswap, a leader in this space, has transformed how users trade cryptocurrencies. Through this article, the ScaleBit Research Group explores the security aspects of Uniswap’s latest version, V4, which brings innovative features with substantial implications for the platform’s functionality and security.","\u003Ccenter>\n    \u003Cimg src=\"\u002Fmedia\u002Fscalebit\u002F2023\u002F07\u002Fe239eb9c748c53a7f6ec2e4cb4aaace7.jpg\">\n    \u003Cbr>\n    \u003Cdiv style=\"\n    display: inline-block;\n    color: #999;\n    padding: 2px;\"> From \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v4\">Uniswap V4\u003C\u002Fa> | Pools with hook contracts diagram\u003C\u002Fdiv>\n\u003C\u002Fcenter>\n\n\u003Cp>In the fast-paced world of decentralized finance (DeFi), exchanges are pivotal in enabling the smooth transfer of assets. Uniswap, a leader in this space, has transformed how users trade cryptocurrencies. Through this article, the ScaleBit Research Group explores the security aspects of Uniswap’s latest version, V4, which brings innovative features with substantial implications for the platform’s functionality and security.\u003C\u002Fp>\n\u003Cp>Uniswap, a decentralized exchange on the Ethereum blockchain, has gained immense popularity due to its permissionless and non-custodial trading pools. With each upgrade, Uniswap has strived to overcome the challenges and limitations of its previous versions. As we delve into Uniswap V4, we’ll examine its new features and their security implications.\u003C\u002Fp>\n\u003Ch2 id=\"Evolution-of-Uniswap-Versions-1-to-3\">\u003Cstrong>Evolution of Uniswap - Versions 1 to 3\u003C\u002Fstrong>\u003C\u002Fh2>\n\u003Cp>Launched on the Ethereum mainnet on November 2, 2018, Uniswap V1 is built on the Automated Market Making (AMM) protocol. This protocol maintains that the product of trading token pairs should always remain constant, where x represents the total balance of token x, and y represents the total balance of token y. The formula can be represented as :\u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fhackmd.io\u002F@HaydenAdams\u002FHJ9jLsfTz?type=view\">1\u003C\u002Fa>\u003C\u002Fp>\n\u003Cp>$$\u003Cbr>x*y = k\u003Cbr>$$\u003C\u002Fp>\n\u003Cp>All functions within Uniswap V1 rely on this simple yet effective formula. In the realm of cryptography, simplicity often brings about robust security.\u003C\u002Fp>\n\u003Cp>However, Uniswap V1 only supports the swapping between Ether (ETH) and ERC20 tokens. Therefore, if users wanted to exchange USDC for DAI, they would first need to swap USDC for ETH, and then swap ETH for DAI. Technically, it’s possible to swap any two ERC20 tokens, provided there is a trading path between them. Nevertheless, this approach can lead to increased costs and significant slippage.\u003C\u002Fp>\n\u003Ccenter>\n    \u003Cimg src=\"\u002Fmedia\u002Fscalebit\u002F2023\u002F07\u002Fb7276eef9025664fe710620fdd6c3ff7.png\">\n    \u003Cbr>\n    \u003Cdiv style=\"\n    display: inline-block;\n    color: #999;\n    padding: 2px;\"> From \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v2#erc20--erc20-pairs\">Uniswap V2\u003C\u002Fa> | DAI to USDC Swap diagram\u003C\u002Fdiv>\n\u003C\u002Fcenter>\n\n\u003Cp>Building upon the success of V1, Uniswap V2 was introduced in May 2020. The team included the ability to swap arbitrary ERC20-ERC20 token pairs, effectively solving the “ETH bridging” problem. Another innovative feature was the flash swap, which allowed users to withdraw any quantity of ERC20 tokens without making upfront payments. Users could return the tokens or pay the fees at the conclusion of the transaction. This function greatly benefited traders without initial capital who still wished to trade, and is similar to the concept of flash loans.\u003C\u002Fp>\n\u003Ccenter>\n    \u003Cimg src=\"\u002Fmedia\u002Fscalebit\u002F2023\u002F07\u002F7c3275bb574a81248a172fdce6c72e83.png\">\n    \u003Cbr>\n    \u003Cdiv style=\"\n    display: inline-block;\n    color: #999;\n    padding: 2px;\"> From \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v2#erc20--erc20-pairs\">Uniswap V2\u003C\u002Fa> | Flash Swaps diagram \u003C\u002Fdiv>\n\u003C\u002Fcenter>\n\n\u003Cp>Alongside updates to business logic, Uniswap V2 also made significant strides in technical security :\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Uniswap V2 properly handles \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fmedium.com\u002Fcoinmonks\u002Fmissing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\">“missing return” ERC20 tokens\u003C\u002Fa> that do not work on Uniswap V1, such as USDT and OMG\u003C\u002Fli>\n\u003Cli>Built in metaTransaction \u003Ccode>approve\u003C\u002Fcode> function for liquidity tokens\u003C\u002Fli>\n\u003Cli>Increase re-entrancy protection using mutex (adds support for ERC777 and other non-standard ERC20 tokens)\u003C\u002Fli>\n\u003Cli>Fix bug from Uniswap V1 that uses all remaining gas on failing transactions\u003C\u002Fli>\n\u003Cli>More descriptive error messages. The above bug caused failing transactions to only return the error “Bad Jump Destination” \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v2\">2\u003C\u002Fa>\n\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>As such, Uniswap V2 was capable of handling distinct tokens and providing a superior user experience.\u003C\u002Fp>\n\u003Cp>Uniswap V3, launched on March 23, 2021, offered enhanced capital efficiency compared to V2. By facilitating low-slippage transaction execution, Uniswap V3 aimed to outperform stablecoin-based AMMs and controlled exchanges.\u003C\u002Fp>\n\u003Cp>Liquidity providers could create personalized pricing curves based on their preferences, enabling them to anticipate the AMM’s form. Liquidity providers’ capital could be concentrated within certain price bands, which improved liquidity at specific prices.\u003C\u002Fp>\n\u003Ccenter>\n    \u003Cimg src=\"\u002Fmedia\u002Fscalebit\u002F2023\u002F07\u002F4103e4b2b3418657797b1f2e4f2a717a.png\">\n    \u003Cbr>\n    \u003Cdiv style=\"\n    display: inline-block;\n    color: #999;\n    padding: 2px;\"> From \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v3\">Uniswap V3\u003C\u002Fa> | Concentrated liquidity diagram\u003C\u002Fdiv>\n\u003C\u002Fcenter>\n\n\u003Cp>One significant change was the enhancement of Oracle price fetching.\u003C\u002Fp>\n\u003Cp>Time-Weighted Average Price (TWAP) oracles, introduced by Uniswap V2, are a vital component of the DeFi architecture and have been adopted in various projects, such as Compound and Reflexer.\u003C\u002Fp>\n\u003Cp>V2 oracles function by maintaining per-second totals of Uniswap pair prices. To determine an accurate TWAP over a period, these pricing amounts can be checked twice: once at the start and once at the end.\u003C\u002Fp>\n\u003Cp>Uniswap V3 significantly upgraded the TWAP oracle, allowing any recent TWAP within the last nine days to be calculated with a single on-chain call. This is accomplished by maintaining several cumulative sums instead of just one.\u003C\u002Fp>\n\u003Ccenter>\n    \u003Cimg src=\"\u002Fmedia\u002Fscalebit\u002F2023\u002F07\u002F02b2811b6f0d55223bb527cb60226b78.png\">\n    \u003Cbr>\n    \u003Cdiv style=\"\n    display: inline-block;\n    color: #999;\n    padding: 2px;\"> From \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v3\">Uniswap V3\u003C\u002Fa> | improved TWAP oracles diagram \u003C\u002Fdiv>\n\u003C\u002Fcenter>\n\n\u003Cp>By employing TWAP, Uniswap effectively reduced the risks of oracle price manipulations, thus increasing community safety.\u003C\u002Fp>\n\u003Cp>Having discussed the main innovations that Uniswap has brought to DeFi and the associated security improvements, it is time to investigate Uniswap V4 and the potential risks it presents.\u003C\u002Fp>\n\u003Ch2 id=\"Uniswap-V4-A-New-Era-of-Customizability-and-Potential-Risks\">Uniswap V4: A New Era of Customizability and Potential Risks\u003C\u002Fh2>\n\u003Ch3 id=\"Understanding-Hooks-in-Uniswap-V4\">Understanding Hooks in Uniswap V4\u003C\u002Fh3>\n\u003Cp>First announced on June 13, 2023, Uniswap V4 introduced the concept of hook contracts alongside other innovative features designed to customize liquidity pools. But what exactly is a hook contract and what potential security risks could arise with V4?\u003C\u002Fp>\n\u003Cp>Hooks are externally deployed contracts that execute certain developer-defined logic at a predetermined stage of a pool’s execution. These hooks allow integrators to construct a specialized liquidity pool with adaptable and flexible execution.\u003C\u002Fp>\n\u003Cp>Hooks can introduce new features and functionalities, modify pool properties, or implement various features, such as:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Executing huge orders gradually using TWAMM\u003C\u002Fli>\n\u003Cli>Onchain limit orders that fill at tick prices\u003C\u002Fli>\n\u003Cli>Dynamic fees that fluctuate with volatility;\u003C\u002Fli>\n\u003Cli>Mechanisms for liquidity providers to internalize MEV;\u003C\u002Fli>\n\u003Cli>Median, truncated, or other special implementations of Oracle \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v2\">5\u003C\u002Fa>\n\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Due to their complexity, which often matches that of full protocols, future separate whitepapers will likely be written to explain specific hook designs.\u003C\u002Fp>\n\u003Cp>When developers create pools on Uniswap V4, they can specify which hook contract to call during the pool’s execution. As of now, Uniswap V4 supports eight such hook callbacks:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>beforeInitialize\u002FafterInitialize\u003C\u002Fli>\n\u003Cli>beforeModifyPosition\u002FafterModifyPosition\u003C\u002Fli>\n\u003Cli>beforeSwap\u002FafterSwap\u003C\u002Fli>\n\u003Cli>beforeDonate\u002FafterDonate \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v2\">5\u003C\u002Fa>\n\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>By applying a specific hook contract during execution, the behaviors and outcomes of such calls are deterministic. The following diagram depicts how the beforeSwap and afterSwap hooks function during the swap execution flow:\u003C\u002Fp>\n\u003Ccenter>\n    \u003Cimg src=\"\u002Fmedia\u002Fscalebit\u002F2023\u002F07\u002F4549191785a568ac787442fd6d91f7d7.png\">\n    \u003Cbr>\n    \u003Cdiv style=\"\n    display: inline-block;\n    color: #999;\n    padding: 2px;\"> From \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v3\">Uniswap V4\u003C\u002Fa> | Swap hook flow \u003C\u002Fdiv>\n\u003C\u002Fcenter>\n\n\u003Cp>However, with great flexibility comes with great risks. User-defined hook contract allow malicious developers create trap contracts to steal the toke or break the system. Though currently we don’t have\u003C\u002Fp>\n\u003Ch3 id=\"Security-Vulnerabilities-in-Uniswap-V4-A-Case-Study\">Security Vulnerabilities in Uniswap V4: A Case Study\u003C\u002Fh3>\n\u003Cp>Right after the whitepaper and draft code of Uniswap V4 were viewable in public, Philogy opened an \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fgithub.com\u002FUniswap\u002Fv4-core\u002Fissues\u002F221\">issue\u003C\u002Fa> describing how a bad owner of \u003Ccode>poolManager\u003C\u002Fcode> could break \u003Ccode>initialize\u003C\u002Fcode> new pools, or selectively censor the creation of pools using sandwich calls.\u003C\u002Fp>\n\u003Cp>First of all, the malicious\u002Fcompromised \u003Ccode>owner\u003C\u002Fcode> of the \u003Ccode>PoolManager\u003C\u002Fcode> can call the \u003Ccode>setProtocolFeeController\u003C\u002Fcode> to set the \u003Ccode>protocolFeeController\u003C\u002Fcode>\u003C\u002Fp>\n\u003Cpre class=\"line-numbers language-javascript\" data-language=\"javascript\">\u003Ccode class=\"language-javascript\">function setProtocolFeeController(IProtocolFeeController controller) external onlyOwner {\n        protocolFeeController = controller;\n        emit ProtocolFeeControllerUpdated(address(controller));\n    }\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Then \u003Ccode>protocolFeeController\u003C\u002Fcode> is called during \u003Ccode>_fetchProtocolFees\u003C\u002Fcode> to fetch the protocol fees\u003C\u002Fp>\n\u003Cpre class=\"line-numbers language-javascript\" data-language=\"javascript\">\u003Ccode class=\"language-javascript\">function _fetchProtocolFees(PoolKey memory key)\n        internal\n        view\n        returns (uint8 protocolSwapFee, uint8 protocolWithdrawFee)\n    {\n        if (address(protocolFeeController) != address(0)) {\n            \u002F\u002F note that EIP-150 mandates that calls requesting more than 63\u002F64ths of remaining gas\n            \u002F\u002F will be allotted no more than this amount, so controllerGasLimit must be set with this\n            \u002F\u002F in mind.\n            if (gasleft() &lt; controllerGasLimit) revert ProtocolFeeCannotBeFetched();\n            try protocolFeeController.protocolFeesForPool{gas: controllerGasLimit}(key) returns (\n                uint8 updatedProtocolSwapFee, uint8 updatedProtocolWithdrawFee\n            ) {\n                protocolSwapFee = updatedProtocolSwapFee;\n                protocolWithdrawFee = updatedProtocolWithdrawFee;\n            } catch {}\n\n            _checkProtocolFee(protocolSwapFee);\n            _checkProtocolFee(protocolWithdrawFee);\n        }\n    }\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>And finally \u003Ccode>_fetchProtocolFees\u003C\u002Fcode> is called inside \u003Ccode>initialize\u003C\u002Fcode> to initialize both \u003Ccode>protocolSwapFee\u003C\u002Fcode> and \u003Ccode>protocolWithdrawFee\u003C\u002Fcode> .\u003C\u002Fp>\n\u003Cpre class=\"line-numbers language-javascript\" data-language=\"javascript\">\u003Ccode class=\"language-javascript\">\u002F\u002F\u002F @inheritdoc IPoolManager\n    function initialize(PoolKey memory key, uint160 sqrtPriceX96) external override returns (int24 tick) {\n        if (key.fee &amp; Fees.STATIC_FEE_MASK &gt;= 1000000) revert FeeTooLarge();\n\n        \u002F\u002F see TickBitmap.sol for overflow conditions that can arise from tick spacing being too large\n        if (key.tickSpacing &gt; MAX_TICK_SPACING) revert TickSpacingTooLarge();\n        if (key.tickSpacing &lt; MIN_TICK_SPACING) revert TickSpacingTooSmall();\n        if (!key.hooks.isValidHookAddress(key.fee)) revert Hooks.HookAddressNotValid(address(key.hooks));\n\n        if (key.hooks.shouldCallBeforeInitialize()) {\n            if (key.hooks.beforeInitialize(msg.sender, key, sqrtPriceX96) != IHooks.beforeInitialize.selector) {\n                revert Hooks.InvalidHookResponse();\n            }\n        }\n\n        PoolId id = key.toId();\n        (uint8 protocolSwapFee, uint8 protocolWithdrawFee) = _fetchProtocolFees(key);\n        (uint8 hookSwapFee, uint8 hookWithdrawFee) = _fetchHookFees(key);\n        tick = pools[id].initialize(sqrtPriceX96, protocolSwapFee, hookSwapFee, protocolWithdrawFee, hookWithdrawFee);\n\n        if (key.hooks.shouldCallAfterInitialize()) {\n            if (key.hooks.afterInitialize(msg.sender, key, sqrtPriceX96, tick) != IHooks.afterInitialize.selector) {\n                revert Hooks.InvalidHookResponse();\n            }\n        }\n\n        emit Initialize(id, key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks);\n    }\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Therefore, there are two ways that a bad protocol fee controller can cause \u003Ccode>initialize\u003C\u002Fcode> always revert:\u003C\u002Fp>\n\u003Col>\n\u003Cli>if the returned value of \u003Ccode>_fetchProtocolFees\u003C\u002Fcode> is not a \u003Ccode>(uint8,uint8)\u003C\u002Fcode> pair, then it will fall into catch and revert.\u003C\u002Fli>\n\u003Cli>Even if the value pair is within the \u003Ccode>uint8\u003C\u002Fcode> type, if they are out of range of \u003Ccode>_checkProtocolFee\u003C\u002Fcode> it will also revert.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Here is the code for checking that the protocol fee is in the valid range:\u003C\u002Fp>\n\u003Cpre class=\"line-numbers language-javascript\" data-language=\"javascript\">\u003Ccode class=\"language-javascript\">function _checkProtocolFee(uint8 fee) internal pure {\n        if (fee != 0) {\n            uint8 fee0 = fee % 16;\n            uint8 fee1 = fee &gt;&gt; 4;\n            \u002F\u002F The fee is specified as a denominator so it cannot be LESS than the MIN_PROTOCOL_FEE_DENOMINATOR (unless it is 0).\n            if (\n                (fee0 != 0 &amp;&amp; fee0 &lt; MIN_PROTOCOL_FEE_DENOMINATOR) || (fee1 != 0 &amp;&amp; fee1 &lt; MIN_PROTOCOL_FEE_DENOMINATOR)\n            ) {\n                revert FeeTooLarge();\n            }\n        }\n    }\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>In the \u003Ccode>_checkProtocolFee\u003C\u002Fcode> function, every 8-bit fee is split into two 4-bit values: \u003Ccode>fee0\u003C\u002Fcode> and \u003Ccode>fee1\u003C\u002Fcode> , if any of these values is non-zero and less than \u003Ccode>MIN_PROTOCOL_FEE_DENOMINATOR\u003C\u002Fcode> (set to 4 in prior codes ) then the function will revert with \u003Ccode>FeeTooLarge\u003C\u002Fcode> error.\u003C\u002Fp>\n\u003Cp>This means that the actual fee fraction for each part of the fee (the swap and withdraw fees) can’t be more than 25%. Note that since these fees are expressed as fractions, a larger value means a smaller fee. For instance, a fee of 8 means “1\u002F8” or 12.5%.\u003C\u002Fp>\n\u003Cp>If you are a bit lost, no worries, we provided a function execution flow diagram co-created by GPT-4.\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fmedia\u002Fscalebit\u002F2023\u002F07\u002F2d6c3d2794233c52f10a78a9105eca68.jpg\" alt=\"Uni\">\u003C\u002Fp>\n\u003Cp>To reproduce the revert case, you can copy this \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fgist.github.com\u002FPhilogy\u002F6a7e4360a677cb38b477542d94222bc5\">PoC\u003C\u002Fa> created by Philogy into \u003Ccode>test\u002Ffoundry-tests\u002FBrickInitialize.t.sol\u003C\u002Fcode>, and run \u003Ccode>forge test --mp test\u002Ffoundry-tests\u002FBrickInitialize.t.sol -vvvv\u003C\u002Fcode> with the \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fbook.getfoundry.sh\u002Fgetting-started\u002Finstallation\">foundry\u003C\u002Fa>.  This PoC shows both two revert scenarios.\u003C\u002Fp>\n\u003Cp>To mitigate this vulnerability, Philogy suggested that there should be a default fee of \u003Ccode>0\u003C\u002Fcode> as the \u003Ccode>try{...} catch{...}\u003C\u002Fcode>pattern implies. Alternatively, it should be made clear that the \u003Ccode>owner\u003C\u002Fcode> of the \u003Ccode>poolManager\u003C\u002Fcode> could control and censor the creation of new pools. It is not sure how Uniswap will solve this issue in the end, but it’s already been moved to their \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fgithub.com\u002Forgs\u002FUniswap\u002Fprojects\u002F27\u002Fviews\u002F1?pane=issue&amp;itemId=30713743\">TODOs\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"Conclusion-Balancing-Innovation-and-Security-in-Uniswap-V4\">Conclusion: Balancing Innovation and Security in Uniswap V4\u003C\u002Fh2>\n\u003Cp>This blog provides both roadmap of Uniswap and in-depth exploration of the security vulnerability of V4, highlighting the balance between innovation and security in the world of decentralized finance. While Uniswap V4 brings exciting new possibilities, it also underscores the importance of rigorous security practices in the development and use of such platforms. As we continue to navigate this rapidly evolving landscape, it is our hope that this analysis will serve as a valuable resource for both users and developers in the DeFi community\u003C\u002Fp>\n\u003Ch2 id=\"Reference\">Reference\u003C\u002Fh2>\n\u003Cp>[1]  \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fhackmd.io\u002F@HaydenAdams\u002FHJ9jLsfTz?type=view\">https:\u002F\u002Fhackmd.io\u002F@HaydenAdams\u002FHJ9jLsfTz?type=view\u003C\u002Fa>\u003C\u002Fp>\n\u003Cp>[2] \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v2#erc20--erc20-pairs\">https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v2\u003C\u002Fa>\u003C\u002Fp>\n\u003Cp>[3] \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v3\">https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v3\u003C\u002Fa>\u003C\u002Fp>\n\u003Cp>[4] \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v4\">https:\u002F\u002Fblog.uniswap.org\u002Funiswap-v4\u003C\u002Fa>\u003C\u002Fp>\n\u003Cp>[5] \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fgithub.com\u002FUniswap\u002Fv4-core\u002Fblob\u002Fmain\u002Fwhitepaper-v4-draft.pdf\">https:\u002F\u002Fgithub.com\u002FUniswap\u002Fv4-core\u002Fblob\u002Fmain\u002Fwhitepaper-v4-draft.pdf\u003C\u002Fa>\u003C\u002Fp>\n\u003Cp>[6] \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fgithub.com\u002FUniswap\u002Fv4-core\u002Fissues\u002F221\">https:\u002F\u002Fgithub.com\u002FUniswap\u002Fv4-core\u002Fissues\u002F221\u003C\u002Fa>\u003C\u002Fp>\n\u003Cp>[7] \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fgist.github.com\u002FPhilogy\u002F6a7e4360a677cb38b477542d94222bc5\">https:\u002F\u002Fgist.github.com\u002FPhilogy\u002F6a7e4360a677cb38b477542d94222bc5\u003C\u002Fa>\u003C\u002Fp>\n\u003Ch2 id=\"About-ScaleBit\">\u003Cstrong>About ScaleBit\u003C\u002Fstrong>\u003C\u002Fh2>\n\u003Cp>ScaleBit is a blockchain security team that provides security solutions for Mass Adoption of Web3. With expertise in scaling technologies like blockchain interoperability and zero-knowledge proofs, we provide meticulous and cutting-edge security audits for blockchain applications. The team comprises security professionals with extensive experience in both academia and enterprise. Our mission is to provide security solutions for Web3 Mass Adoption and make security accessible for all.\u003C\u002Fp>\n\u003Cp>Website: \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Fwww.scalebit.xyz\u002F\">https:\u002F\u002Fwww.scalebit.xyz\u002F\u003C\u002Fa>\u003C\u002Fp>\n\u003Cp>Twitter: \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Ftwitter.com\u002Fscalebit_\">https:\u002F\u002Ftwitter.com\u002Fscalebit_\u003C\u002Fa>\u003C\u002Fp>\n\u003Chr>\n\u003Cp>Write by \u003Ca target=\"_blank\" rel=\"noopener\" href=\"https:\u002F\u002Ftwitter.com\u002FNormanrockon\">0xNorman\u003C\u002Fa> from ScaleBit Research Group\u003C\u002Fp>","\u002Fmedia\u002Fscalebit\u002F2023\u002F07\u002F3618e57532636b52035db21d3ca2f7c6.png","In the fast-paced world of decentralized finance (DeFi), exchanges are pivotal in enabling the smooth transfer of assets. Uniswap, a leader in this space, has transformed how users trade cryptocurrencies. Through this article, the ScaleBit Research Group explores the security aspects of Uniswap’s latest version, V4, wh","2023-07-26T03:15:00Z","2026-08-19T16:35:04Z","10 min read",true,"Uniswap V4：Analyzing the Security Landscape Beneath the Surface cover image",1792473989148]