Jointventure Finance Rug Pull
What happened
JointVenture (JVF) has an owner-only function named burnFrom(address account, uint256 balance, uint256 subtractValue) that burns nothing: it writes the caller-supplied balance minus subtractValue straight into _balances[account] and into _totalSupply, with no check against the account's real balance, so the owner can give any address any token amount. On 2021-01-13 Etherscan shows the deployer address 0x69a97A46…a4b63F locking 10,000 JVF at 19:44:18 UTC (tx 0x6077ef8c…3c4dbc), adding 60 ETH and 50,000 JVF of liquidity at 19:46:45 UTC (tx 0xde4ad6af…f4ed7e), calling burnFrom on itself with balance 1e27 (1,000,000,000 JVF) and subtractValue 0 at 20:03:55 UTC (tx 0xa9d1f673…f4415e), and then swapping 1,000,000,000 JVF for 63.93 ETH on Uniswap V2 at 20:04:52 UTC (tx 0x05e5b1fd…22439b).
How it happened
- The constructor mints an initial amount to the deployer and makes it owner:
_balances[msg.sender] = _balances[msg.sender].add(initialTokens);andcontract JointVenture is Context, IERC20 , Ownable. The deployer locked 10,000 JVF and put 50,000 JVF plus 60 ETH into a new Uniswap V2 pool. burnFromisexternal ownerOnlyand ignores the account's actual balance:_balances[account] = balance.sub(subtractValue, "ERC20: burn amount exceeds balance");followed by_totalSupply = balance.sub(subtractValue);. Whateverbalancethe owner passes becomes the account's balance and the total supply.- At 20:03:55 UTC the deployer called
burnFrom(account = 0x69a97A46aC3bbc3E12f2887C33164F1736a4b63F, balance = 1e27, subtractValue = 0). That set its own balance, and the recorded total supply, to 1,000,000,000 JVF, 20,000 times the 50,000 JVF in the pool. The token's on-chaintotalSupplyread at 2026-09-30 is 1,000,000,000 JVF, the value this call writes. - At 20:04:52 UTC the deployer sold 1,000,000,000 JVF through Uniswap V2 Router 2 (
swapExactTokensForETH) and received 63.93 ETH. - The deployer had added 60 ETH to the pool, so the difference of about 3.93 ETH came from other traders' ETH already in the pool (arithmetic from the two Etherscan pages); selling a token amount 20,000 times the pool's JVF reserve into a constant-product pool takes out nearly all of its ETH (arithmetic; pool reserves after the swap were not read).
Protocol details
Evidence
- report JointVenture source (Sourcify repository) repo.sourcify.dev
- transaction Etherscan transaction: burnFrom call etherscan.io
- transaction Etherscan transaction: swap of 1.00 B JVF for 63.93 ETH etherscan.io
- transaction Etherscan transaction: addLiquidityETH for JVF etherscan.io
- transaction Etherscan transaction: lockTokens for 10,000 JVF etherscan.io
- address JointVenture verified source (Etherscan code tab) etherscan.io
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.