// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract TestContract1 {
address public owner = msg.sender;
function setOwner(address _owner) public {
require(msg.sender == owner, "not owner");
owner = _owner;
}
}
contract TestContract2 {
address public owner = msg.sender;
uint public value = msg.value;
uint public x;
uint public y;
/*
payable 可以在调用这笔函数的消息中附带以太币
*/
constructor(uint _x, uint _y) payable{
x = _x;
y = _y;
}
}
contract Proxy {
// 事件:向链外汇报部署的地址
event Deploy(address);
/*
returns 返回新部署的地址
*/
function deploy(bytes memory _code) external payable returns (address addr){
// 内联汇编
assembly {
// create(v, p, n)
// v = 部署合约发送的以太坊主币的数量(msg.value可以代表主币数量,但内联汇编中不能这样使用)
// p = 内存中机器码开始的位置
// n = 内存中机器码的大小
addr := create(callvalue(), add(_code, 0x20), mload(_code))
}
require (addr != address(0), "deploy failed");
emit Deploy(addr); // 触发事件
}
/*
代理合约部署合约1的时候需要设置合约1的所有者
*/
function execute(address _target, bytes memory _data) external payable {
(bool success, ) = _target.call {value: msg.value}(_data);
require(success, "failed");
}
}
// 助手合约
contract Helper {
// 获取被部署合约的机器码
function getBytecode1() external pure returns (bytes memory) {
bytes memory bytecode = type(TestContract1).creationCode;
return bytecode;
}
// 获取被部署合约(含构造函数)的机器码
function getBytecode2(uint _x, uint _y) external pure returns (bytes memory) {
bytes memory bytecode = type(TestContract2).creationCode;
return abi.encodePacked(bytecode, abi.encode(_x, _y));
}
// 设置管理员,注意return行中字符串为TestContract1设置拥有者的方法签名
function getCalldata(address _owner) external pure returns (bytes memory) {
return abi.encodeWithSignature("setOwner(address)", _owner);
}
}
部署代理合约&助手合约
部署合约1
通过助手合约获取合约1的机器码
通过代理合约部署合约1
通过汇报地址加载合约1
设置合约1的所有者
设置前
设置
通过助手合约打包个人地址
通过代理合约设置合约1地址
设置后
设置后的所有者已变更为助手打包的个人地址