您当前的位置: 首页 >  以太坊

mutourend

暂无认证

  • 1浏览

    0关注

    661博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

以太坊Solidity合约动态部署合约策略

mutourend 发布时间:2022-03-03 14:28:37 ,浏览量:1

1. 引言

在Solidity合约中动态部署合约的方案有:

  • 1)Wormhole 1.0 中的deployWrappedAsset:https://github.com/certusone/wormhole/blob/v1.3.0/ethereum/contracts/Wormhole.sol#L212
  • 2)Optics Bridge中的_deployToken:https://github.com/celo-org/optics-monorepo/blob/main/solidity/optics-xapps/contracts/bridge/TokenRegistry.sol#L174
2. Wormhole 1.0中的deployWrappedAsset

需先部署相应的WrappedAsset合约。参考https://github.com/OpenZeppelin/openzeppelin-sdk/blob/master/packages/lib/contracts/upgradeability/ProxyFactory.sol。 前序博客有:

  • Wormhole资产跨链项目代码解析
  • Wormhole漏洞分析

详细代码为:

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;
    }

在Wormhole 2.0中,部署Wrapped合约的方式不再由合约部署,改为外部调用部署:

	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. Optics Bridge中的_deployToken

需先部署相应的BridgeToken合约。实际部署依赖可参看:tokenBeacon依赖关系 前序博客有:

  • 以太坊Solidity合约升级策略

详细代码为:

	/**
     * @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);
    }

合约部署合约交易示例为:【对比https://etherscan.io/tx/0x43a0836d748ccdc431a2ef63f0fbb51eeb201114db605eb19d8c693809395900 仅proveAndProcess的gas为188K,而 部署token合约+proveAndProcess的gas为633K。所以部署token合约的gas约为445K。】

  • https://etherscan.io/tx/0x8551f21595d38719fa95b0cf5d334119b3d401f5bbe4f80823fde1ede8f0ef72/advanced#eventlog

部署的token的地址为:

  • https://etherscan.io/address/0x7118057ff0f4fd0994fb9d2d94de8231d5cca79e#events

从Optics BridgeRouter合约中读取: https://etherscan.io/address/0x4fc16De11deAc71E8b2Db539d82d93BE4b486892#readProxyContract

在这里插入图片描述 从https://explorer.celo.org/address/0x74c0C58B99b68cF16A717279AC2d056A34ba2bFe/contracts 可知,部署的该token对应为Celo链上的Source token。

关注
打赏
1664532908
查看更多评论
立即登录/注册

微信扫码登录

0.0371s