{"note": {"noteId": 468, "projectId": 18, "author": "0xbf9fe7767f57780b106756fcd22dfe53394eb81c", "authorName": "0xbf9f...b81c", "authorHandle": null, "authorVerified": false, "authorShort": "0xbf9f...b81c", "source": "reef", "status": "", "alsoReports": 0, "separateFrom": 0, "kind": 3, "kindLabel": "context", "inReplyTo": 0, "fingerprint": "0x8cf240780969d8b652e2e160b42c32600d6dd9a25ea3ffc9f5827523ed6fd8ff", "content": "{\"action\":\"added\",\"credit\":\"Kept by SunWeb3Sec (github.com/SunWeb3Sec/DeFiHackLabs), Apache-2.0.\",\"day\":\"2026-11-04\",\"kind\":\"watch-hack\",\"lost\":\"Lost: ~$555K drained from the pair / ~$541K payout reported (estimate). This PoC forks one block before the exploit tx and reconstructs the attacker side with a fresh contract and typed interface calls on the real verified contracts, no vm.mock, no vm.store and no vm.prank of any protocol identity (the single vm.prank relocates the attacker's own pre-held TENDRIL working capital from its holder contract into the fresh exploit contract, not a protocol account): it takes the real 30,641,402 USDT flash loan from the PancakeSwap Infinity Vault (no deal() for the borrowed USDT), buys TENDRIL ammo through the unrestricted USDT-FLAP-TENDRIL route, skews the pair with a 4,097,517 USDT buy, then sells back in one swap whose 30% tax auto-triggers the controller's sellToken and controlburn, draining the pair's USDT reserve from 555,670 to ~0 and repaying the loan in the same lock. Net profit 308,959.367543173232679069 USDT, matching the on-chain profit sweep to the wei; the attacker's net is below the full drained reserve because the controller routed part of it to its own fee recipients. The attacker's ~33.06B TENDRIL of pre-positioned working capital was accumulated permissionlessly, not from any privileged source: funding address 0xb87cf5 bought it across 57 ordinary USDT swaps from the unrestricted secondary USDT/TENDRIL pool 0xda0bc72c over ~11 days (net ~7.4K USDT), then moved it to the exploit contract in a setup tx ~147 blocks before the exploit. That secondary pool is depleted at the fork block, so the amount cannot be re-bought atomically on the fork; the PoC forks after the accumulation and relocates the real, already-held on-chain balance into the fresh exploit contract rather than deal()-minting it. It is ordinary attacker capital, not the flash-borrowed asset and not the exploited value\",\"name\":\"TENDRIL\",\"path\":\"src/test/2026-11/TENDRIL_exp.sol\",\"receipts\":[{\"label\":\"The commit\",\"url\":\"https://github.com/SunWeb3Sec/DeFiHackLabs/commit/fd58d7e0593ad02034213189f807a64fcbbb8796\"},{\"label\":\"Replay file\",\"url\":\"https://github.com/SunWeb3Sec/DeFiHackLabs/blob/e6a9d80a61a88672acb5c2ce979522ed79246ea0/src/test/2026-11/TENDRIL_exp.sol\"},{\"label\":\"README section\",\"url\":\"https://github.com/SunWeb3Sec/DeFiHackLabs/blob/e6a9d80a61a88672acb5c2ce979522ed79246ea0/README.md#20261104-tendril-tendril-s-transfer-taxes-any-non-privileged-sell-into-its-usdt-pair-30-and-as-a-side-effect-of-that-same-transfer-calls-the-pool-controller-s-selltoken-which-dumps-the-controller-s-accumulated-tendril-into-the-pair-for-usdt-and-controlburns-the-pair-s-tendril-reserve-by-about-twice-the-sell-amount-with-no-price-or-reserve-guard-the-flash-loan-the-swaps-and-the-tax-triggered-selltoken-path-are-all-reachable-by-a-fresh-contract-with-no-role-so-the-attacker-flash-borrows-30-6m-usdt-from-the-pancakeswap-infinity-vault-skews-the-pair-with-a-buy-that-the-token-forces-out-to-the-controller-then-one-taxed-sell-makes-the-controller-burn-the-pair-down-to-dust-so-the-untaxed-remainder-of-the-sell-swaps-against-a-near-zero-reserve-and-takes-the-pair-s-whole-usdt-balance-flash-loan-repaid-in-the-same-lock\"}],\"recordedAt\":\"2026-11-13T03:10:48Z\",\"sourceId\":\"defihacklabs\",\"text\":\"DeFiHackLabs added a replay of the TENDRIL attack from November 4, 2026. The replay is a test anyone can run to see how it worked. Their notes say: Lost: ~$555K drained from the pair / ~$541K payout reported (estimate). This PoC forks one block before the exploit tx and reconstructs the attacker side with a fresh contract and typed interface calls on the real verified contracts, no vm.mock, no vm.store and no vm.prank of any protocol identity (the single vm.prank relocates the attacker's own pre-held TENDRIL working capital from its holder contract into the fresh exploit contract, not a protocol account): it takes the real 30,641,402 USDT flash loan from the PancakeSwap Infinity Vault (no deal() for the borrowed USDT), buys TENDRIL ammo through the unrestricted USDT-FLAP-TENDRIL route, skews the pair with a 4,097,517 USDT buy, then sells back in one swap whose 30% tax auto-triggers the controller's sellToken and controlburn, draining the pair's USDT reserve from 555,670 to ~0 and repaying the loan in the same lock. Net profit 308,959.367543173232679069 USDT, matching the on-chain profit sweep to the wei; the attacker's net is below the full drained reserve because the controller routed part of it to its own fee recipients. The attacker's ~33.06B TENDRIL of pre-positioned working capital was accumulated permissionlessly, not from any privileged source: funding address 0xb87cf5 bought it across 57 ordinary USDT swaps from the unrestricted secondary USDT/TENDRIL pool 0xda0bc72c over ~11 days (net ~7.4K USDT), then moved it to the exploit contract in a setup tx ~147 blocks before the exploit. That secondary pool is depleted at the fork block, so the amount cannot be re-bought atomically on the fork; the PoC forks after the accumulation and relocates the real, already-held on-chain balance into the fresh exploit contract rather than deal()-minting it. It is ordinary attacker capital, not the flash-borrowed asset and not the exploited value.\",\"v\":1}", "structured": null, "uri": "", "txHash": "0xb606c03e00769bd496c29971dd0a94d66b4b83b6d75de3d950dab0e3b66d396c", "receiptUrl": "https://flare-explorer.flare.network/tx/0xb606c03e00769bd496c29971dd0a94d66b4b83b6d75de3d950dab0e3b66d396c", "blockNumber": 74406305, "voice": null, "voiceReceipt": null, "amendmentReason": null, "amendmentFingerprint": null, "retractedReason": null, "authorTier": 1, "factors": ["Verified"], "withheld": null, "checkResults": [], "parsed": {"action": "added", "credit": "Kept by SunWeb3Sec (github.com/SunWeb3Sec/DeFiHackLabs), Apache-2.0.", "day": "2026-11-04", "kind": "watch-hack", "lost": "Lost: ~$555K drained from the pair / ~$541K payout reported (estimate). This PoC forks one block before the exploit tx and reconstructs the attacker side with a fresh contract and typed interface calls on the real verified contracts, no vm.mock, no vm.store and no vm.prank of any protocol identity (the single vm.prank relocates the attacker's own pre-held TENDRIL working capital from its holder contract into the fresh exploit contract, not a protocol account): it takes the real 30,641,402 USDT flash loan from the PancakeSwap Infinity Vault (no deal() for the borrowed USDT), buys TENDRIL ammo through the unrestricted USDT-FLAP-TENDRIL route, skews the pair with a 4,097,517 USDT buy, then sells back in one swap whose 30% tax auto-triggers the controller's sellToken and controlburn, draining the pair's USDT reserve from 555,670 to ~0 and repaying the loan in the same lock. Net profit 308,959.367543173232679069 USDT, matching the on-chain profit sweep to the wei; the attacker's net is below the full drained reserve because the controller routed part of it to its own fee recipients. The attacker's ~33.06B TENDRIL of pre-positioned working capital was accumulated permissionlessly, not from any privileged source: funding address 0xb87cf5 bought it across 57 ordinary USDT swaps from the unrestricted secondary USDT/TENDRIL pool 0xda0bc72c over ~11 days (net ~7.4K USDT), then moved it to the exploit contract in a setup tx ~147 blocks before the exploit. That secondary pool is depleted at the fork block, so the amount cannot be re-bought atomically on the fork; the PoC forks after the accumulation and relocates the real, already-held on-chain balance into the fresh exploit contract rather than deal()-minting it. It is ordinary attacker capital, not the flash-borrowed asset and not the exploited value", "name": "TENDRIL", "path": "src/test/2026-11/TENDRIL_exp.sol", "receipts": [{"label": "The commit", "url": "https://github.com/SunWeb3Sec/DeFiHackLabs/commit/fd58d7e0593ad02034213189f807a64fcbbb8796"}, {"label": "Replay file", "url": "https://github.com/SunWeb3Sec/DeFiHackLabs/blob/e6a9d80a61a88672acb5c2ce979522ed79246ea0/src/test/2026-11/TENDRIL_exp.sol"}, {"label": "README section", "url": "https://github.com/SunWeb3Sec/DeFiHackLabs/blob/e6a9d80a61a88672acb5c2ce979522ed79246ea0/README.md#20261104-tendril-tendril-s-transfer-taxes-any-non-privileged-sell-into-its-usdt-pair-30-and-as-a-side-effect-of-that-same-transfer-calls-the-pool-controller-s-selltoken-which-dumps-the-controller-s-accumulated-tendril-into-the-pair-for-usdt-and-controlburns-the-pair-s-tendril-reserve-by-about-twice-the-sell-amount-with-no-price-or-reserve-guard-the-flash-loan-the-swaps-and-the-tax-triggered-selltoken-path-are-all-reachable-by-a-fresh-contract-with-no-role-so-the-attacker-flash-borrows-30-6m-usdt-from-the-pancakeswap-infinity-vault-skews-the-pair-with-a-buy-that-the-token-forces-out-to-the-controller-then-one-taxed-sell-makes-the-controller-burn-the-pair-down-to-dust-so-the-untaxed-remainder-of-the-sell-swaps-against-a-near-zero-reserve-and-takes-the-pair-s-whole-usdt-balance-flash-loan-repaid-in-the-same-lock"}], "recordedAt": "2026-11-13T03:10:48Z", "sourceId": "defihacklabs", "text": "DeFiHackLabs added a replay of the TENDRIL attack from November 4, 2026. The replay is a test anyone can run to see how it worked. Their notes say: Lost: ~$555K drained from the pair / ~$541K payout reported (estimate). This PoC forks one block before the exploit tx and reconstructs the attacker side with a fresh contract and typed interface calls on the real verified contracts, no vm.mock, no vm.store and no vm.prank of any protocol identity (the single vm.prank relocates the attacker's own pre-held TENDRIL working capital from its holder contract into the fresh exploit contract, not a protocol account): it takes the real 30,641,402 USDT flash loan from the PancakeSwap Infinity Vault (no deal() for the borrowed USDT), buys TENDRIL ammo through the unrestricted USDT-FLAP-TENDRIL route, skews the pair with a 4,097,517 USDT buy, then sells back in one swap whose 30% tax auto-triggers the controller's sellToken and controlburn, draining the pair's USDT reserve from 555,670 to ~0 and repaying the loan in the same lock. Net profit 308,959.367543173232679069 USDT, matching the on-chain profit sweep to the wei; the attacker's net is below the full drained reserve because the controller routed part of it to its own fee recipients. The attacker's ~33.06B TENDRIL of pre-positioned working capital was accumulated permissionlessly, not from any privileged source: funding address 0xb87cf5 bought it across 57 ordinary USDT swaps from the unrestricted secondary USDT/TENDRIL pool 0xda0bc72c over ~11 days (net ~7.4K USDT), then moved it to the exploit contract in a setup tx ~147 blocks before the exploit. That secondary pool is depleted at the fork block, so the amount cannot be re-bought atomically on the fork; the PoC forks after the accumulation and relocates the real, already-held on-chain balance into the fresh exploit contract rather than deal()-minting it. It is ordinary attacker capital, not the flash-borrowed asset and not the exploited value.", "v": 1}}, "parsed": {"action": "added", "credit": "Kept by SunWeb3Sec (github.com/SunWeb3Sec/DeFiHackLabs), Apache-2.0.", "day": "2026-11-04", "kind": "watch-hack", "lost": "Lost: ~$555K drained from the pair / ~$541K payout reported (estimate). This PoC forks one block before the exploit tx and reconstructs the attacker side with a fresh contract and typed interface calls on the real verified contracts, no vm.mock, no vm.store and no vm.prank of any protocol identity (the single vm.prank relocates the attacker's own pre-held TENDRIL working capital from its holder contract into the fresh exploit contract, not a protocol account): it takes the real 30,641,402 USDT flash loan from the PancakeSwap Infinity Vault (no deal() for the borrowed USDT), buys TENDRIL ammo through the unrestricted USDT-FLAP-TENDRIL route, skews the pair with a 4,097,517 USDT buy, then sells back in one swap whose 30% tax auto-triggers the controller's sellToken and controlburn, draining the pair's USDT reserve from 555,670 to ~0 and repaying the loan in the same lock. Net profit 308,959.367543173232679069 USDT, matching the on-chain profit sweep to the wei; the attacker's net is below the full drained reserve because the controller routed part of it to its own fee recipients. The attacker's ~33.06B TENDRIL of pre-positioned working capital was accumulated permissionlessly, not from any privileged source: funding address 0xb87cf5 bought it across 57 ordinary USDT swaps from the unrestricted secondary USDT/TENDRIL pool 0xda0bc72c over ~11 days (net ~7.4K USDT), then moved it to the exploit contract in a setup tx ~147 blocks before the exploit. That secondary pool is depleted at the fork block, so the amount cannot be re-bought atomically on the fork; the PoC forks after the accumulation and relocates the real, already-held on-chain balance into the fresh exploit contract rather than deal()-minting it. It is ordinary attacker capital, not the flash-borrowed asset and not the exploited value", "name": "TENDRIL", "path": "src/test/2026-11/TENDRIL_exp.sol", "receipts": [{"label": "The commit", "url": "https://github.com/SunWeb3Sec/DeFiHackLabs/commit/fd58d7e0593ad02034213189f807a64fcbbb8796"}, {"label": "Replay file", "url": "https://github.com/SunWeb3Sec/DeFiHackLabs/blob/e6a9d80a61a88672acb5c2ce979522ed79246ea0/src/test/2026-11/TENDRIL_exp.sol"}, {"label": "README section", "url": "https://github.com/SunWeb3Sec/DeFiHackLabs/blob/e6a9d80a61a88672acb5c2ce979522ed79246ea0/README.md#20261104-tendril-tendril-s-transfer-taxes-any-non-privileged-sell-into-its-usdt-pair-30-and-as-a-side-effect-of-that-same-transfer-calls-the-pool-controller-s-selltoken-which-dumps-the-controller-s-accumulated-tendril-into-the-pair-for-usdt-and-controlburns-the-pair-s-tendril-reserve-by-about-twice-the-sell-amount-with-no-price-or-reserve-guard-the-flash-loan-the-swaps-and-the-tax-triggered-selltoken-path-are-all-reachable-by-a-fresh-contract-with-no-role-so-the-attacker-flash-borrows-30-6m-usdt-from-the-pancakeswap-infinity-vault-skews-the-pair-with-a-buy-that-the-token-forces-out-to-the-controller-then-one-taxed-sell-makes-the-controller-burn-the-pair-down-to-dust-so-the-untaxed-remainder-of-the-sell-swaps-against-a-near-zero-reserve-and-takes-the-pair-s-whole-usdt-balance-flash-loan-repaid-in-the-same-lock"}], "recordedAt": "2026-11-13T03:10:48Z", "sourceId": "defihacklabs", "text": "DeFiHackLabs added a replay of the TENDRIL attack from November 4, 2026. The replay is a test anyone can run to see how it worked. Their notes say: Lost: ~$555K drained from the pair / ~$541K payout reported (estimate). This PoC forks one block before the exploit tx and reconstructs the attacker side with a fresh contract and typed interface calls on the real verified contracts, no vm.mock, no vm.store and no vm.prank of any protocol identity (the single vm.prank relocates the attacker's own pre-held TENDRIL working capital from its holder contract into the fresh exploit contract, not a protocol account): it takes the real 30,641,402 USDT flash loan from the PancakeSwap Infinity Vault (no deal() for the borrowed USDT), buys TENDRIL ammo through the unrestricted USDT-FLAP-TENDRIL route, skews the pair with a 4,097,517 USDT buy, then sells back in one swap whose 30% tax auto-triggers the controller's sellToken and controlburn, draining the pair's USDT reserve from 555,670 to ~0 and repaying the loan in the same lock. Net profit 308,959.367543173232679069 USDT, matching the on-chain profit sweep to the wei; the attacker's net is below the full drained reserve because the controller routed part of it to its own fee recipients. The attacker's ~33.06B TENDRIL of pre-positioned working capital was accumulated permissionlessly, not from any privileged source: funding address 0xb87cf5 bought it across 57 ordinary USDT swaps from the unrestricted secondary USDT/TENDRIL pool 0xda0bc72c over ~11 days (net ~7.4K USDT), then moved it to the exploit contract in a setup tx ~147 blocks before the exploit. That secondary pool is depleted at the fork block, so the amount cannot be re-bought atomically on the fork; the PoC forks after the accumulation and relocates the real, already-held on-chain balance into the fresh exploit contract rather than deal()-minting it. It is ordinary attacker capital, not the flash-borrowed asset and not the exploited value.", "v": 1}, "project": {"projectId": 18, "name": "DeFi hack replays (DeFiHackLabs)", "kind": "watch", "keeper": "SunWeb3Sec", "jurisdiction": "", "markText": "DH", "shape": "", "what": "DeFiHackLabs, a collection of tests that replay public DeFi attacks so anyone can see how they worked", "repoUrl": "https://github.com/SunWeb3Sec/DeFiHackLabs", "credit": "Kept by SunWeb3Sec (github.com/SunWeb3Sec/DeFiHackLabs), Apache-2.0.", "chunk": "item"}, "date": "2026-11-13", "author": {"name": "Flare Reef watcher", "handle": "", "verified": false}}