当前位置:澳门金莎娱乐网站 > 澳门金莎娱乐手机版 > 中国央行,金融合约与智能合约

中国央行,金融合约与智能合约

文章作者:澳门金莎娱乐手机版 上传时间:2019-11-02

  中国央行:6月底外币对本币远期合约和期货合约空头头寸289亿美元

原文链接
date:20170710

怎样向尚未接触过比特币理念的人介绍以太坊及智能合约在金融合约方面的应用?下面是一种尝试。首先介绍区块链,解释它为什么值得人们的信任,其次介绍智能合约,然后介绍以太坊系统,最后介绍智能合约与金融合约的结合。

进入【新浪财经股吧】讨论

Solidity中合约的概念和其他面向对象语言中的类差不多。他们都有状态变量来存储永久数据,有函数来改变这些数据。调用不同的合约(实例)的函数其实是执行EVM的函数调用,并且会改变上下文,原上下文中的变量就变得不可访问了。

比特币的共识机制

创建合约

合约可以从“外部”创建或者从Solidity合约中创建。当合约创建的时候,合约的构造函数(跟合约的名称相同)就会执行一次。

构造函数是可选的。但是只允许有一个构造函数,这意味着不支持重载。

web3.js中,例如javascript API,如下所示:

// 需要指定源码,包含合约名称(?Need to specify some source including contract name for the data param below)
var source = "contract CONTRACT_NAME { function CONTRACT_NAME(uint a, uint b) {} }";

// 编译器生成的json格式的abi 数组
var abiArray = [
    {
        "inputs":[
            {"name":"x","type":"uint256"},
            {"name":"y","type":"uint256"}
        ],
        "type":"constructor"
    },
    {
        "constant":true,
        "inputs":[],
        "name":"x",
        "outputs":[{"name":"","type":"bytes32"}],
        "type":"function"
    }
];

var MyContract_ = web3.eth.contract(source);
MyContract = web3.eth.contract(MyContract_.CONTRACT_NAME.info.abiDefinition);
// 发布新合约
var contractInstance = MyContract.new(
    10,
    11,
    {from: myAccount, gas: 1000000}
);

在内部,构造函数的参数在构造函数代码创建之后才被传递进去,但是如果你是使用web3.js,你就无须关心这个问题。

如果一个合约想要创建另一个合约,那么必须要给创建者提供创建合约的源码(和二进制数据)。这意味这循环依赖创建是不可行的。

pragma solidity ^0.4.0;

contract OwnedToken {
    // TokenCreator 是一个合约类型数据,在下面代码中定义
    // 当他没有被用来创建一个合约的时候,这样引用是没有问题的。
    TokenCreator creator;
    address owner;
    bytes32 name;

    // 这是一个构造函数,在其中注册了创建者,并给name变量赋值。
    function OwnedToken(bytes32 _name) {
        // 状态变量可以通过变量名来访问,而不是通过this.owner.
        // 这个准则也同样适用于函数,尤其是在构造函数中。
        // 你只能通过“内部调用”的方式来调用他们。
        // 因为合约本身都没有创建。
        owner = msg.sender;
        // 我们通过显式类型转换将`address`转换为`TokenCreator`类型。
        // 并且假设调用合约的类型是TokenCreator。其实并没有方法来检验的。
        creator = TokenCreator(msg.sender);
        name = _name;
    }

    function changeName(bytes32 newName) {
        // 只有创建者才能改变名称。
        // 以下的比较是可行的,因为合约隐式的转换为地址类型.
        if (msg.sender == address(creator))
            name = newName;
    }

    function transfer(address newOwner) {
        // 只有当前拥有者才能交易token
        if (msg.sender != owner) return;
        // 交易之后,我们同样要知道是否交易成功。
        // 注意,这里调用了其他函数,函数在下面定义。
        // 如果调用失败,例如gas不足,执行会马上在此停止。
        if (creator.isTokenTransferOK(owner, newOwner))
            owner = newOwner;
    }
}

contract TokenCreator {
    function createToken(bytes32 name)
       returns (OwnedToken tokenAddress)
    {
        // 创建新的Token合约,并返回他的地址。
        // 在Javascript侧,返回的类型只是简单的`address`
        // 因为在ABI中最接近的可用的类型。
        return new OwnedToken(name);
    }

    function changeName(OwnedToken tokenAddress, bytes32 name) {
        // 同样, 外部类型"tokenAddress"只是简单的"address"类型.
        tokenAddress.changeName(name);
    }

    function isTokenTransferOK(
        address currentOwner,
        address newOwner
    ) returns (bool ok) {
        // 监测任意条件
        address tokenAddress = msg.sender;
        return (keccak256(newOwner) & 0xff) == (bytes20(tokenAddress) & 0xff);
    }
}

比特币的核心技术区块链可以理解成可复制、共享的账本。

可见性和getter

我们知道,函数调用有两种方式(内部调用并不会产生真实的EVM调用(也被成为消息调用)但是外部函数会),但是函数和状态变量的可见性有四种。
函数可以被指定为external,public,internal或者private,默认是public的。对于状态变量,external是非法的,默认是internal

external:
外部函数是合约接口的一部分,意味着可以通过交易从其他合约中调用。外部函数f不能在内部被调用(例如,f()是不可行的,但是this.f()是可以的)。有时候外部函数的执行效率会更高,当他们收到很大的数组数据的时候。

public:
公有函数是合约接口的一部分,可以通过内部或者消息来调用。对于公有的状态变量,会自动创建getter函数。

internal:
这些函数和变量只能在内部调用(例如,从当前合约或者从该合约派生的合约),不需要this前缀。

private:
私有函数和状态变量只能在他们定义的合约中可见,在派生的合约中不可见。

注意:合约里的所有都对外部观察者可见。private只是为了阻止其他合约访问和改变信息,但是可以区块链中可见。

可见性指示在类型和变量名之间,对于函数,可见性的位置在参数列表和返回值之间。

pragma solidity ^0.4.0;

contract C {
    function f(uint a) private returns (uint b) { return a   1; }
    function setData(uint a) internal { data = a; }
    uint public data;
}

在以下的例子中,合约D可以调用c.getData()来获取data中的数据。但是不能调用f函数。合约E是从合约C派生而来,因此,可以调用compute

// 注释不会被编译

pragma solidity ^0.4.0;

contract C {
    uint private data;

    function f(uint a) private returns(uint b) { return a   1; }
    function setData(uint a) { data = a; }
    function getData() public returns(uint) { return data; }
    function compute(uint a, uint b) internal returns (uint) { return a b; }
}


contract D {
    function readData() {
        C c = new C();
        uint local = c.f(7); // 错误,f不可见
        c.setData(3);
        local = c.getData();
        local = c.compute(3, 5); // 错误"compute" 不可见
    }
}


contract E is C {
    function g() {
        C c = new C();
        uint val = compute(3, 5);  // acces to internal member (from derivated to parent contract)
    }
}

比特币的最核心创新:它教会世界如何在不需要信任第三方的情况下远距离转移价值。

getter函数

编译器会给所有的公有变量生成getter函数。以下的合约,编译器会生成一个data函数,没有其他参数并返回uint类型的data变量的值。变量在定义的时候会进行初始化。

pragma solidity ^0.4.0;

contract C {
    uint public data = 42;
}

contract Caller {
    C c = new C();
    function f() {
        uint local = c.data();
    }
}

getter函数在外部可见。如果通过内部调用的方式访问(没有this),就会当作是状态变量。如果通过外部的方式调用(有this),就会当作是函数。

pragma solidity ^0.4.0;

contract C {
    uint public data;
    function x() {
        data = 3; //内部访问
        uint val = this.data(); // 外部访问
    }
}

以下的例子会更加复杂:

pragma solidity ^0.4.0;

contract Complex {
    struct Data {
        uint a;
        bytes3 b;
        mapping (uint => uint) map;
    }
    mapping (uint => mapping(bool => Data[])) public data;
}

将会生成如下函数:

function data(uint arg1, bool arg2, uint arg3) returns (uint a, bytes3 b) {
    a = data[arg1][arg2][arg3].a;
    b = data[arg1][arg2][arg3].b;
}

注意,结构体中的mapping被忽略了,因为没有好的方法来为mapping提供key。

人们当然可以面对面地转移实体纸币,但是,在比特币出现以前,我们做不到:在不需要信任中心化第三方机构的情况,远距离向某人转移价值。

函数修改器(function modifiers)

修改器可以用来轻易的改变函数的执行效果。例如,他们可以在执行函数之前自动的检查先决条件。修改器可以继承,并且可以被派生合约复写。

pragma solidity ^0.4.11;

contract owned {
    function owned() { owner = msg.sender; }
    address owner;

    // This contract only defines a modifier but does not use
    // it - it will be used in derived contracts.
    // The function body is inserted where the special symbol
    // "_;" in the definition of a modifier appears.
    // This means that if the owner calls this function, the
    // function is executed and otherwise, an exception is
    // thrown.
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
}


contract mortal is owned {
    // This contract inherits the "onlyOwner"-modifier from
    // "owned" and applies it to the "close"-function, which
    // causes that calls to "close" only have an effect if
    // they are made by the stored owner.
    function close() onlyOwner {
        selfdestruct(owner);
    }
}


contract priced {
    // Modifiers can receive arguments:
    modifier costs(uint price) {
        if (msg.value >= price) {
            _;
        }
    }
}


contract Register is priced, owned {
    mapping (address => bool) registeredAddresses;
    uint price;

    function Register(uint initialPrice) { price = initialPrice; }

    // It is important to also provide the
    // "payable" keyword here, otherwise the function will
    // automatically reject all Ether sent to it.
    function register() payable costs(price) {
        registeredAddresses[msg.sender] = true;
    }

    function changePrice(uint _price) onlyOwner {
        price = _price;
    }
}

contract Mutex {
    bool locked;
    modifier noReentrancy() {
        require(!locked);
        locked = true;
        _;
        locked = false;
    }

    /// This function is protected by a mutex, which means that
    /// reentrant calls from within msg.sender.call cannot call f again.
    /// The `return 7` statement assigns 7 to the return value but still
    /// executes the statement `locked = false` in the modifier.
    function f() noReentrancy returns (uint) {
        require(msg.sender.call());
        return 7;
    }
}

函数可以有多个修改器,通过空格隔开。修改器的执行顺序为排列顺序。

警告:在Solidity早期版本中,在函数中的return表达式有修改器的会有不同的执行效果。

Explicit returns from a modifier or function body only leave the current modifier or function body。返回变量被赋值并且控制流会在先前修改器的“ _ ”符号之后继续。

修改器允许任意表达式,所有对函数可见的符号对于修改器都是可见的。修改器中引入的符号在函数中并不可见(因为他们可能会被复写)。

就好像银行和支付系统的传统转账模式的基础设施被重构为点对点支付网络。这种转变如下图所示:

静态状态变量

状态变量可以被声明为constant。在这个情况下,变量必须在编译的时候被表达式赋于静态的值。所有访问storage,区块链数据(如now,this.balance或者block.number)或者执行数据(msg.gas)或者调用外部合约都是不允许的。在内存分配上可能会有单边效应的表达式是允许的,但是那些对其他内存对象有单边效应的是不允许的。(?Expressions that might have a side-effect on memory allocation are allowed, but those that might have a side-effect on other memory objects are not. )内建函数keccak256,sha256,ripemd160,ecrecover,addmodmulmod是允许的(尽管他们调用了外部合约)。

允许内存分配单边效应的原因是它可以构建更加复杂的对象,例如查找表。这个功能还没有完全可用。

编译器不会对这些变量保留内存片,并且每个静态变量都会被替换为各自的静态表达式(优化器会计算表达式的值)。

现在还没有实现所有的静态类型。支持的类型是值类型和字符串。

pragma solidity ^0.4.0;

contract C {
    uint constant x = 32**22   8;
    string constant text = "abc";
    bytes32 constant myHash = keccak256("abc");
}

图片 1

本文由澳门金莎娱乐网站发布于澳门金莎娱乐手机版,转载请注明出处:中国央行,金融合约与智能合约

关键词: www.4166.com