развертывание любого контракта - demonoved/A-trial-run-in-solidity GitHub Wiki

// SPDX-License-Identifier: MIT
// compiler version must be greater than or equal to 0.8.20 and less than 0.9.0
pragma solidity ^0.8.23;
//развернем любой контракт вызвав proxy.deploy
//можно получить байт код контракта вызвав getBytecode
contract Proxy {
    event Deploy(address);
    receive() external payable {}
    function deploy(bytes memory _code) external payable returns (address addr){
        assembly {
            //cоздаем (v,p,n)
            // v = количество ETH для отправки
            // p = указатель в памяти на начало кода
            // n = размер кода
            addr := create(callvalue(), add(_code, 0x20),mload(_code))
        }
        // обратный адрес 0 при ошибке
        require(addr != address(0), "deploy failed"); // сбой развертывания
        emit Deploy(addr);
    }
    function execute(address _target, bytes memory _data) external payable {
        (bool success, ) = _target.call{value: msg.value}(_data);
        require(success, "failed");
    }
}
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;
    
    constructor(uint _x, uint _y) payable {
        x = _x;
        y = _y;
    }
}
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));
    }
    function getCalldata(address _owner) external pure returns (bytes memory){
        return abi.encodeWithSignature("setOwner(address)", _owner);
    }
}
  1. Proxy Contract:

    • Объявлен с нужным компилятором (pragma solidity ^0.8.23), что означает, что он должен быть скомпилирован с версией Solidity 0.8.23 или выше, но меньше 0.9.0.
    • Имеет функцию deploy, позволяющую развертывать другие контракты. Она использует низкоуровневую функцию create в inline assembly, для создания нового контракта по предоставленному байт-коду и отправляет указанное количество эфиров с транзакцией.
    • Имеет функцию execute, позволяющая выполнять вызовы функций на других контрактах.
    • Отправляет событие Deploy, когда новый контракт успешно развернут.
  2. TestContract1 Contract:

    • Устанавливает owner как отправителя сообщения (адрес, который создал контракт).
    • Содержит функцию setOwner для изменения владельца контракта, с проверкой, что только текущий владелец может это сделать.
  3. TestContract2 Contract:

    • Помимо установления owner, контракт также имеет значение value, равное количеству эфиров, отправленных при создании контракта.
    • У контракта есть две переменные x и y, которые нужно установить при создании контракта.
    • Контракт имеет конструктор, который принимает x и y в качестве аргументов и должен быть развернут с указанием этих значений.
  4. Helper Contract:

    • Предназначен для вывода байт-кода контрактов TestContract1 и TestContract2, чтобы они могли быть развернуты через Proxy контракт.
    • Использует функцию getBytecode1, чтобы получить байт-код TestContract1.
    • Использует функцию getBytecode2, чтобы получить байт-код TestContract2 и кодирует аргументы конструктора вместе с байт-кодом.
    • Содержит функцию getCalldata, которая кодирует вызов функции setOwner с новым адресом владельца для последующего помещения в функцию execute контракта Proxy.

Цель этих контрактов - использовать Proxy для деплоя других контрактов (TestContract1 и TestContract2) и последующего взаимодействия с развернутыми контрактами (например, изменения владельца). Это является примером фабрики контрактов и делегирования вызовов в Ethereum smart contracts.