1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.7.0 <0.9.0;
  3. contract TestContract1 {
  4. address public owner = msg.sender;
  5. function setOwner(address _owner) public {
  6. require(msg.sender == owner, "not owner");
  7. owner = _owner;
  8. }
  9. }
  10. contract TestContract2 {
  11. address public owner = msg.sender;
  12. uint public value = msg.value;
  13. uint public x;
  14. uint public y;
  15. /*
  16. payable 可以在调用这笔函数的消息中附带以太币
  17. */
  18. constructor(uint _x, uint _y) payable{
  19. x = _x;
  20. y = _y;
  21. }
  22. }
  23. contract Proxy {
  24. // 事件:向链外汇报部署的地址
  25. event Deploy(address);
  26. /*
  27. returns 返回新部署的地址
  28. */
  29. function deploy(bytes memory _code) external payable returns (address addr){
  30. // 内联汇编
  31. assembly {
  32. // create(v, p, n)
  33. // v = 部署合约发送的以太坊主币的数量(msg.value可以代表主币数量,但内联汇编中不能这样使用)
  34. // p = 内存中机器码开始的位置
  35. // n = 内存中机器码的大小
  36. addr := create(callvalue(), add(_code, 0x20), mload(_code))
  37. }
  38. require (addr != address(0), "deploy failed");
  39. emit Deploy(addr); // 触发事件
  40. }
  41. /*
  42. 代理合约部署合约1的时候需要设置合约1的所有者
  43. */
  44. function execute(address _target, bytes memory _data) external payable {
  45. (bool success, ) = _target.call {value: msg.value}(_data);
  46. require(success, "failed");
  47. }
  48. }
  49. // 助手合约
  50. contract Helper {
  51. // 获取被部署合约的机器码
  52. function getBytecode1() external pure returns (bytes memory) {
  53. bytes memory bytecode = type(TestContract1).creationCode;
  54. return bytecode;
  55. }
  56. // 获取被部署合约(含构造函数)的机器码
  57. function getBytecode2(uint _x, uint _y) external pure returns (bytes memory) {
  58. bytes memory bytecode = type(TestContract2).creationCode;
  59. return abi.encodePacked(bytecode, abi.encode(_x, _y));
  60. }
  61. // 设置管理员,注意return行中字符串为TestContract1设置拥有者的方法签名
  62. function getCalldata(address _owner) external pure returns (bytes memory) {
  63. return abi.encodeWithSignature("setOwner(address)", _owner);
  64. }
  65. }

部署代理合约&助手合约

部署合约 - 图1

部署合约 - 图2

部署合约1

通过助手合约获取合约1的机器码

部署合约 - 图3

通过代理合约部署合约1

部署合约 - 图4

通过汇报地址加载合约1

部署合约 - 图5

设置合约1的所有者

设置前

部署合约 - 图6

设置

通过助手合约打包个人地址

部署合约 - 图7

通过代理合约设置合约1地址

部署合约 - 图8

设置后

设置后的所有者已变更为助手打包的个人地址

部署合约 - 图9

部署合约2

通过助手合约获取合约2的机器码

部署合约 - 图10

通过代理合约部署合约2

部署合约 - 图11部署合约 - 图12

通过汇报地址加载合约2

部署合约 - 图13

观察合约2的各项参数

部署合约 - 图14