以太坊合约交易怎么玩(以太坊永续合约怎么玩)

以太坊智能合约,其运行过程,相比普通的应用程序运行过程,还是挺特别的,在此说明一下。

整个以太坊智能合约运行过程,包括发布、调用执行。

一、智能合约发布

智能合约的发布过程,本身也是一个区块链交易,因此也是需要经过出块处理的,这样就需要矿工将智能合约进行打包,通过挖矿获取区块后,把智能合约写入到区块链中。这里写入到区块链的智能合约,其实就是一长串字节码,类似如下:

6000341115600c57600080fd5b6012608d565b636d4ce63c811460355763371303c0811460455763b3bcfa828114604f57600080fd5b6041603d605b565b60b6565b6056565b604b6069565b6056565b6055607b565b5b5060c5565b6000606360c0565b54905090565b60016071605b565b01607860c0565b55565b60016083605b565b03608a60c0565b55565b60007c010000000000000000000000000000000000000000000000000000000060003504905090565b8060005260206000f35b600090565b

这些字节码,其实都能翻译成汇编语言,对照翻译过程类似如下:

以太坊合约交易怎么玩(以太坊永续合约怎么玩)

图1 字节码汇编对照

这就是为什么智能合约字节码,能够在以太坊EVM虚拟机中运行的原因。这里顺带提一下,以太坊EVM虚拟机,是一个256位的准图灵机,之所以采用256位设计,主要是为了方便做256位hash计算、椭圆曲线密码计算。

这里特别注意一点,智能合约发布的时候,如果智能合约存在带参数的构造函数,则需要在发布时,传递构造函数参数,否则智能合约发布会失败。

二、智能合约运行

智能合约发布到链上后,会得到一个智能合约在区块链上的地址,类似如下:

0x89C760facaAA256737723218Eb561958E6ef8141

根据此地址,即可对对应的智能合约的外部函数发起调用。这里要说明:

1、智能合约一经发布,就不能更改了(原因就是因为智能合约发布上链了,而区块链是不可篡改的),别人知道这个智能合约的地址,就可以对其发起调用(当然,合约本身存在调用校验逻辑,那是代码层面的事情了)。这个智能合约的代码修改后再发布,其合约地址就是全新的地址,不会影响之前已经发布的智能合约地址的有效性的。因此智能合约代码发布前一定要严格审核和测试,一经发布就不能更改了,不像传统的程序代码,发现bug可以修复代码再发布进行bug修复。

2、智能合约发布后不能修改,但是如果代码里预留有selfdestruct删除智能合约的外部函数设计,则是可以进行删除操作的(一般这样的删除操作函数,会设定只有合约拥有者才能调用的)。

3、智能合约一旦在公链发布,任何人都可以对智能合约的外部函数发起调用。由于这个特性,因此,智能合约的数据结构设计、逻辑设计要非常仔细斟酌。

智能合约的每次被调用,都会涉及数据处理,在数据层面,有三种模式的数据:

1、内存数据(memory),通过memory修饰的变量数据,都是内存数据,只会在函数调用期间存在,调用完毕数据马上消亡。注意,所有函数内部定义的变量,默认都是内存数据;

2、调用数据(calldata),通过calldata修饰的变量数据,是一个特殊只读数据位置,用来保存函数调用参数,调用完毕数据马上消亡;

3、存储数据(storage),所有的状态变量、函数里使用storage修饰的变量,都是存储数据,所有的存储数据,函数调用完毕后,都会持久化存储到区块链上,因此,这些数据的gas损耗非常大。注意,因为存储数据每次函数调用都会持久化到区块链上,所以这些数据是在智能合约的多次函数调用间共享的,因此这些数据的结构设计要考虑这个共享效应。注意,所有合约成员变量,默认都是存储数据:


contract Counter {
    uint256 count = 0; //存储数据
    address payable owner;
    struct callSenders {
        mapping(address => bool) senderMaps;
        address[] senders;
    }
    callSenders datas;
    constructor() {
        owner = payable(msg.sender);
    }

    function increment() external {
        require(!datas.senderMaps[msg.sender]);
        uint256 step = 10; //内存数据
        count = count + step;
        datas.senderMaps[msg.sender] = true;
        datas.senders.push(msg.sender);
    }

    function getCount() external view returns (uint256, address[] memory) {
        return (count, senders2);
    }

    function kill() public {
        if (owner == msg.sender) {
            selfdestruct(owner);
        }
    }
}

a、如果存储数据需要进行按调用者区分,那么数据结构要增加调用者地址存储标识(一般采用mapping),便于实现不同调用者的存储数据隔离;

b、如果存储数据不能按调用者区分,则要考虑好多调用者多次函数调用的数据锁问题;

c、存储数据如果需要追溯,则要做好保存历史状况的结构设计,便于追溯;

d、存储数据的结构,在满足业务需求的情况下,越简单越好,因为简单gas开销就小;

智能合约每次被调用后,可以理解会就进入休眠状态,等待下一次的外部调用,只不过每次调用,存储数据会存储到区块链上,供下一次调用使用。

游戏工作室 关注币宇公众号:BiYuClub  备注:游戏打金

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 sumchina520@foxmail.com 举报,一经查实,本站将立刻删除。
如若转载,请注明出处:https://www.kingj520.com/9725.html