如何将部署代码发送到 ethers.js 中的 CREATE2 合约?

问题描述 投票:0回答:1

我部署了一个

CREATE2
智能合约,用作部署其他代码的工厂。目前仅部署一种合约:

import { MyERC1155 } from "./MyERC1155.sol";

contract MyCreate2Factory {
    event ContractDeployed(address contractAddress);

    function deployContract(
        string calldata name,
        string calldata symbol,
        string calldata baseURI,
        string calldata contractURI,
        bytes32 salt
    ) external {
        address contractAddress;

        bytes memory deploymentCode = bytes.concat(
            type(MyERC1155).creationCode,
            abi.encode(name, symbol, baseURI, contractURI)
        );

        assembly {
            contractAddress := create2(0, add(deploymentCode, 0x20), mload(deploymentCode), salt)
            if iszero(extcodesize(contractAddress)) {
                revert(0, 0)
            }
        }

        emit ContractDeployed(contractAddress);
    }
}

这效果很好,我可以在 ethers.js 中将参数发送给它,如下所示:

const proxy = await ethers.getContractFactory('MyCreate2Factory');
const factory = (await proxy.deploy()) as unknown as MyCreate2Factory;
await factory.deployTransaction.wait();

await expect(factory.deployContract(name, symbol, baseURI, contractURI, salt))
  .to.emit(factory, 'ContractDeployed')
  .withArgs(expectedContractAddress); // Pass

但现在我想制作一个新的

CREATE2
合约,能够部署任何合约,所以我将其更改为:

contract AnyCreate2Factory {
    event ContractDeployed(address contractAddress);

    function deployContract(bytes32 salt, bytes memory bytecode) external {
        address contractAddress;

        assembly {
            contractAddress := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
            if iszero(extcodesize(contractAddress)) {
                revert(0, 0)
            }
        }

        emit ContractDeployed(contractAddress);
    }
}

但是我很难复制 Solidity 如何在 ethers.js 中生成

deploymentCode
。我在本地有 ABI 和字节码,所以我想用它来发送到部署函数,但出现一些错误。这就是我正在尝试的:

import myERC1155Interface from '../artifacts/contracts/MyERC1155.sol/MyERC1155.json';

const { abi, bytecode } = myERC1155Interface;
const constructorTypes = ['string', 'string', 'string', 'string'];
const constructorArgs = [name, symbol, baseURI, contractURI];

const initCode = ethers.utils.concat([
  bytecode,
  ethers.utils.defaultAbiCoder.encode(constructorTypes, constructorArgs)
]);

await expect(factory.deployContract(salt, initCode))
  .to.emit(factory, 'ContractDeployed')
  .withArgs(expectedContractAddress);

但是,我收到有关交易块大小的错误:

InvalidInputError: Transaction gas limit is 1000395544 and exceeds block gas limit of 1000000000

我是否错过了实现此目标的步骤,或者这是不可能的?

typescript ethereum solidity ethers.js evm
1个回答
0
投票

您是正确的,initCode 变量中的字节码对于单个事务来说太大。区块 Gas 上限为 100,000,000,您的交易使用超过 100,000,000 Gas。

要使用 CREATE2 和大字节码部署合约,可以使用以下步骤:

*将字节码分割成多个块。

*部署存储字节码块的合约。

*使用 CREATE2 和存储字节码块的合约地址部署目标合约。

以下是如何在 ethers.js 中执行此操作的示例:

import { ethers } from 'ethers';

// Split the bytecode into chunks.
const bytecodeChunks = bytecode.split('\n');

// Deploy a contract that stores the bytecode chunks.
class BytecodeStore {
  constructor(bytecodeChunks) {
    this.bytecodeChunks = bytecodeChunks;
  }

  async deploy(signer) {
    const contractFactory = await ethers.getContractFactory(BytecodeStore, { signer });
    const contract = await contractFactory.deploy(this.bytecodeChunks);
    return contract;
  }
}

// Deploy your target contract using CREATE2 and the address of the contract that stores the bytecode chunks.
class MyERC1155 {
  constructor(bytecodeStoreAddress) {
    this.bytecodeStoreAddress = bytecodeStoreAddress;
  }

  async deploy(signer, salt) {
    const bytecode = bytecodeChunks.reduce((a, b) => a + b, '');
    const initCode = ethers.utils.concat([
      bytecode,
      ethers.utils.defaultAbiCoder.encode(constructorTypes, constructorArgs)
    ]);

    const contractFactory = await ethers.getContractFactory(MyERC1155, { signer });
    const contract = await contractFactory.deploy(salt, this.bytecodeStoreAddress);
    return contract;
  }
}

// Deploy the bytecode store contract.
const bytecodeStore = await new BytecodeStore(bytecodeChunks).deploy(signer);

// Deploy the target contract.
const myERC1155 = await new MyERC1155(bytecodeStore.address).deploy(signer, salt);

这种方法将允许您部署具有大字节码的合约,而不会超过区块气体限制。

© www.soinside.com 2019 - 2024. All rights reserved.