Ethereum Solidity contract dynamically deploys contract strategy

1 Introduction

The options for dynamically deploying contracts in Solidity contracts are:

2. Wormhole 1.0deployWrappedAsset

The corresponding WrappedAsset contract needs to be deployed first. Refer to https://github.com/OpenZeppelin/openzeppelin-sdk/blob/master/packages/lib/contracts/upgradeability/ProxyFactory.sol .
The pre-order blogs are:

The detailed code is:

function deployWrappedAsset(bytes32 seed, uint8 token_chain, bytes32 token_address, uint8 decimals) private returns (address asset){
        // Taken from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/master/packages/lib/contracts/upgradeability/ProxyFactory.sol
        // Licensed under MIT
        bytes20 targetBytes = bytes20(wrappedAssetMaster);
        assembly {
            let clone := mload(0x40)
            mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(clone, 0x14), targetBytes)
            mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            asset := create2(0, clone, 0x37, seed)
        }

        // Call initializer
        WrappedAsset(asset).initialize(token_chain, token_address, decimals);

        // Store address
        wrappedAssets[seed] = asset;
        isWrappedAsset[asset] = true;
    }

In Wormhole 2.0, the way to deploy Wrapped contracts is no longer by contract deployment, but by external call deployment:

	function createWrapped(bytes memory encodedVm) external returns (address token) {
        (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVm);

        require(valid, reason);
        require(verifyBridgeVM(vm), "invalid emitter");

        BridgeStructs.AssetMeta memory meta = parseAssetMeta(vm.payload);
        return _createWrapped(meta, vm.sequence);
    }

    // Creates a wrapped asset using AssetMeta
    function _createWrapped(BridgeStructs.AssetMeta memory meta, uint64 sequence) internal returns (address token) {
        require(meta.tokenChain != chainId(), "can only wrap tokens from foreign chains");
        require(wrappedAsset(meta.tokenChain, meta.tokenAddress) == address(0), "wrapped asset already exists");

        // initialize the TokenImplementation
        bytes memory initialisationArgs = abi.encodeWithSelector(
            TokenImplementation.initialize.selector,
            bytes32ToString(meta.name),
            bytes32ToString(meta.symbol),
            meta.decimals,
            sequence,

            address(this),

            meta.tokenChain,
            meta.tokenAddress
        );

        // initialize the BeaconProxy
        bytes memory constructorArgs = abi.encode(address(this), initialisationArgs);

        // deployment code
        bytes memory bytecode = abi.encodePacked(type(BridgeToken).creationCode, constructorArgs);

        bytes32 salt = keccak256(abi.encodePacked(meta.tokenChain, meta.tokenAddress));

        assembly {
            token := create2(0, add(bytecode, 0x20), mload(bytecode), salt)//部署合约

            if iszero(extcodesize(token)) {
                revert(0, 0)
            }
        }

        setWrappedAsset(meta.tokenChain, meta.tokenAddress, token);
    }
    
	function setWrappedAsset(uint16 tokenChainId, bytes32 tokenAddress, address wrapper) internal {
        _state.wrappedAssets[tokenChainId][tokenAddress] = wrapper;
        _state.isWrappedAsset[wrapper] = true;
    }

3. In Optics Bridge_deployToken

The corresponding BridgeToken contract needs to be deployed first. For the actual deployment dependencies, please refer to: tokenBeacon dependencies
The pre-order blogs are:

The detailed code is:

	/**
     * @notice Deploy and initialize a new token contract
     * @dev Each token contract is a proxy which
     * points to the token upgrade beacon
     * @return _token the address of the token contract
     */
    function _deployToken(bytes29 _tokenId) internal returns (address _token) {
        // deploy and initialize the token contract
        _token = address(new UpgradeBeaconProxy(tokenBeacon, ""));
        // initialize the token separately from the
        IBridgeToken(_token).initialize();
        // set the default token name & symbol
        string memory _name;
        string memory _symbol;
        (_name, _symbol) = _defaultDetails(_tokenId);
        IBridgeToken(_token).setDetails(_name, _symbol, 18);
        // store token in mappings
        representationToCanonical[_token].domain = _tokenId.domain();
        representationToCanonical[_token].id = _tokenId.id();
        canonicalToRepresentation[_tokenId.keccak()] = _token;
        // emit event upon deploying new token
        emit TokenDeployed(_tokenId.domain(), _tokenId.id(), _token);
    }

The example of contract deployment contract transaction is: [Compare https://etherscan.io/tx/0x43a0836d748ccdc431a2ef63f0fbb51eeb201114db605eb19d8c693809395900 only the gas of the proveAndProcess is 188K, while the gas of the token contract +proveAndProcess is 633K. So the gas for deploying the token contract is about 445K.

The address of the deployed token is:

Read from Optics BridgeRouter contract:
https://etherscan.io/address/0x4fc16De11deAc71E8b2Db539d82d93BE4b486892#readProxyContract

insert image description here
From https://explorer.celo.org/address/0x74c0C58B99b68cF16A717279AC2d056A34ba2bFe/contracts , the deployed token corresponds to the Source token on the Celo chain.

Guess you like

Origin blog.csdn.net/mutourend/article/details/123250798
Recommended