3分钟Solidity: 9.4 最小代理合约

23 阅读3分钟

欢迎订阅专栏3分钟Solidity--智能合约--Web3区块链技术必学

如需获取本内容的最新版本,请参见 Cyfrin.io 上的“最小代理合同(代码示例)”

如果你有一个需要多次部署的合约,可以使用最小代理合约来低成本地进行部署。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

// original code
// https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol

contract MinimalProxy {
    function clone(address target) external returns (address result) {
        // 将地址转换为20字节
        bytes20 targetBytes = bytes20(target);

        // 实际代码 //
        // 3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3

        // 创建代码 //
        // 将运行时代码复制到内存中并返回
        // 3d602d80600a3d3981f3

        // 运行时代码 //
        // 代码委托调用地址
        // 363d3d373d3d3d363d73 address 5af43d82803e903d91602b57fd5bf3

        assembly {
            /*
            读取从存储在0x40地址的指针开始的32字节内存

            在Solidity中,内存中的0x40槽位具有特殊意义:
            它存储着"空闲内存指针",该指针指向当前已分配内存的末端。
            */
            let clone := mload(0x40)
            // 将32字节存储到以“clone”为起始地址的内存中
            mstore(
                clone,
                0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
            )

            /*
              |              20 bytes                |
            0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
                                                      ^
                                                      pointer
            */
            // 将32字节存储到从"clone"起始位置偏移20字节的内存中
            // 0x14 = 20
            mstore(add(clone, 0x14), targetBytes)

            /*
              |               20 bytes               |                 20 bytes              |
            0x3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe
                                                                                              ^
                                                                                              pointer
            */
            // 将32字节存储到从"clone"起始位置偏移40字节的内存中
            // 0x28 = 40
            mstore(
                add(clone, 0x28),
                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
            )

            /*
              |               20 bytes               |                 20 bytes              |           15 bytes          |
            0x3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3
            */
            // 创建新合约
            // 发送 0 以太币
            // 代码从存储在“clone”中的指针开始
            // 代码大小 0x37(55 字节)
            result := create(0, clone, 0x37)
        }
    }
}

Remix Lite 尝试一下