solidity create2 学习

简介: solidity create2 学习
salt

nonce,也可以自己生成

create

address = hash(msg.sender,nonce)

create2

deploymentData= creationCode+constructorArgs

address =hash(“0xff”,msg.sender,nonce,hash(deploymentData))

可以不用部署直接可以获取合约地址

address(this)

相当于A合约中调用了B(uint)的构造方法创建了B合约

// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

contract A{
   function test8() public pure returns (bytes4 a,bytes4 b){
     //获取methodId
     //合约名字,方法名字
      a = B.getBalance.selector;
      b = bytes4(keccak256(abi.encodePacked("getBalance()")));
   }

    function testCreate2(uint _number) public  returns (address bAddr){
        //获取createCode
        bytes memory cCode = type(B).creationCode;
        //构造方法参数编码
        bytes memory args = abi.encode(_number);
        //生成bytescode
        bytes memory deploymentData =  abi.encodePacked(cCode,args);
        //利用参数生成salt
        bytes32 salt = keccak256(abi.encodePacked(_number));
         assembly {
            bAddr := create2(0x0, add(0x20, deploymentData), mload(deploymentData), salt)
        }
        require(address(bAddr) != address(0), "Create2 call failed");
    }

     // 提前计算合约地址
        function calculateAddr(uint _number) public view returns(address bAddr){

         //获取createCode
        bytes memory cCode = type(B).creationCode;
        //构造方法参数编码
        bytes memory args = abi.encode(_number);
        //生成bytescode
        bytes memory deploymentData =  abi.encodePacked(cCode,args);
        //利用参数生成salt
        bytes32 salt = keccak256(abi.encodePacked(_number));
            // 计算合约地址方法 hash()
            bytes memory params =   abi.encodePacked(
                bytes1(0xff),
                address(this),
                salt,
                keccak256(deploymentData)
            );
            bytes32  params2 = keccak256(params);
            uint params3 =  uint(params2);
            bAddr = address(uint160(params3));
        }

}


contract B{

    uint public b = 10;
    constructor(uint _b) public{
        b = _b;
    }

    event anTest(uint indexed addr) anonymous;
    
    function getBalance() view public returns (uint){
      return address(this).balance;
    }
    receive () payable external{
        emit anTest(msg.value);
    }

    fallback () payable external{

    }

}


clone-factory
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;


contract TestA{
    uint public a;

    constructor(){}

    function setA(uint _a)public {
        a = _a;
    }
    function getAB(uint b) view public  returns (uint c){
        c= a+b;
    }

}


contract ContractFactory{
    address public implementation;
    bytes public code;
    bytes32 public codeHash;   
    event ProxyCreated(address indexed _address, bytes32 _salt);
    event ImplementationChanged(address indexed _implementation, bytes32 _codeHash, bytes _code);

   
    function getSalt(uint _number)  pure public returns (bytes32){
        return keccak256(abi.encodePacked(_number));
    }

    function setImplementation(address _implementation) public {
        require(
            _implementation != address(0),
            "ContractFactory#_setImplementation: INVALID_IMPLEMENTATION"
        );
        // Adapted from https://github.com/optionality/clone-factory/blob/32782f82dfc5a00d103a7e61a17a5dedbd1e8e9d/contracts/CloneFactory.sol
        code = abi.encodePacked(
            hex"3d602d80600a3d3981f3363d3d373d3d3d363d73",
            _implementation,
            hex"5af43d82803e903d91602b57fd5bf3"
        );
        codeHash = keccak256(code);
        implementation = _implementation;

        emit ImplementationChanged(implementation, codeHash, code);
    }

     function getAddress(uint _number) public view returns (address _addr) {
        return address(
            uint160(uint256(
                keccak256(
                    abi.encodePacked(
                        bytes1(0xff),
                        address(this),
                        getSalt(_number),
                        codeHash
                    )
                )
            ))
        );
    }
    function createProxy(uint _number, bytes memory _data) public virtual returns (address addr) {
        bytes memory slotcode = code;
        // solium-disable-next-line security/no-inline-assembly
        bytes32 salt  = getSalt(_number);
        assembly {
            addr := create2(0, add(slotcode, 0x20), mload(slotcode), salt)
        }
        require(addr != address(0), "ContractFactory#createProxy: CREATION_FAILED");

        emit ProxyCreated(addr, salt);

        if (_data.length > 0) {
            (bool success,) = addr.call(_data);
            require(success, "ContractFactory#createProxy: CALL_FAILED");
        }
    }

  
}


shr shl使用 两个值生成唯一的值,通过唯一值获取对应的两个值


  function encodeTokenId(uint256 _itemId, uint256 _issuedId) public pure returns (uint256 id) {
        require(_itemId <= MAX_ITEM_ID, "encodeTokenId: INVALID_ITEM_ID");
        require(_issuedId <= MAX_ISSUED_ID, "encodeTokenId: INVALID_ISSUED_ID");

        // solium-disable-next-line security/no-inline-assembly
        assembly {
            id := or(shl(ISSUED_ID_BITS, _itemId), _issuedId)
        }
    }

    /**
     * @notice Decode token id
     * @dev itemId (`itemIdBits` bits) + issuedId (`issuedIdBits` bits)
     * @param _id - token id
     * @return itemId uint256 of the item id
     * @return issuedId uint256 of the issued id
     */
    function decodeTokenId(uint256 _id) public pure returns (uint256 itemId, uint256 issuedId) {
        uint256 mask = MAX_ISSUED_ID;
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            itemId := shr(ISSUED_ID_BITS, _id)
            issuedId := and(mask, _id)
        }
    }
相关文章
|
7月前
|
安全 Go API
go 语言调用openstack
Go语言可以通过REST API来调用OpenStack服务,例如通过OpenStack的Keystone服务进行身份验证,并使用其他服务(如Nova、Glance、Neutron等)执行操作。以下是使用Go语言调用OpenStack的一般步骤: 1. **身份验证(Authentication)**: - 使用Keystone服务获取身份认证令牌(token)。 - 你可以使用用户名/密码、项目(tenant)名称、以及其他必要的信息进行身份验证。 2. **调用其他OpenStack服务**: - 通过HTTP请求调用相应的OpenStack服务,比如Nova(计算服
160 0
|
3月前
|
存储 Go
Go to Learn Go之类型转换
Go to Learn Go之类型转换
41 7
|
7月前
|
编译器 Go
Go 语言函数
Go 语言函数
34 7
|
存储 Cloud Native Go
GO 语言的函数??
GO 语言的函数??
|
存储 Go
Go学习笔记-Go 浮点数设计原理
Go学习笔记-Go 浮点数设计原理
118 0
|
编译器 Go
学习笔记 | Go testing 里的巧妙设计
学习笔记 | Go testing 里的巧妙设计
74 0
|
测试技术 Go
Go 编程 | 连载 35 - testing 标准库的其他功能
Go 编程 | 连载 35 - testing 标准库的其他功能
Go 编程 | 连载 35 - testing 标准库的其他功能
|
Go Python
Go 语言快速入门指南:Go 函数
函数是一段代码的片段,包含连续的执行语句,它可以将零个或多个输入参数映射到零个或多个参数输出。函数像一个黑盒,对它的使用者隐藏实现细节。还可以在代码中通过函数调用来执行它们。
Go 语言快速入门指南:Go 函数
|
存储 Java 编译器
Go 语言快速入门指南:Go 指针
我们都知道,Java、C#、Python 都 因为指针的复杂而避开了指针的用法,改成了引用。 Go 语言作为 21 世纪的 C 语言,自然保留了 C 语言的许多特性,指针就是其一。但相比于 C 的指针,Go 对指针做了很多限制。 这一篇,就来学习 Go 指针的各种相关知识。
Go 语言快速入门指南:Go 指针
|
存储 Java Go
Go 语言快速入门指南:Go 结构体(上)
有时,你需要一组不同类型的数据,例如人的信息,包括姓名(字符串)、年龄(整型)、身高和体重(浮点型);又如学生记录,混合保存学生名字和成绩(浮点数)。 此时,无法用切片或者映射来保存。但是你可以使用结构体类型 struct 的类型来保存。 本文让我们一起来学习结构体的相关知识吧!
Go 语言快速入门指南:Go 结构体(上)