合约函数的使用

1. constant function和非constant function

函数调用从对链上属性是否有更改可分为两种:constant function 和 非constant function。 Constant function 是指用 view/pure/constant 修饰的函数。会在调用的节点上直接返回结果,并不以一笔交易的形式广播出去。 非constant function是指需要依托一笔交易的形式被广播的方法调用。函数会改变链上数据的内容,比如转账,改变合约内部变量的值等等。

注意: 如果在合约内部使用create指令(CREATE instruction),即使用view/pure/constant来修饰这个动态创建的合约合约方法,这个合约方法仍会被当作非constant function,以交易的形式来处理。

2. 消息调用(message calls)

消息调用可以向其他的合约发起函数调用,也可以向合约的账户或非合约的账户转帐trx。 与普通的波场triggercontract类似, 消息调用也有调用的发起者,接受者,数据,转账金额,扣费,以及返回值等属性。每一个消息调用都可以递归的生成新的消息调用。 合约可以决定在其内部的消息调用中,对于剩余的 energy ,应发送和保留多少。如果在内部消息调用时发生了OutOfEnergyException 异常(或其他任何异常),会返回false,但不会以异常的形式抛出。此时,只有与该内部消息调用一起发送的energy会被消耗掉,如果不表明消息调用所传入的费用call.value(energy),则会扣掉所有的剩余energy。

3. 委托调用/代码调用和库 (delegatecall/callcode/library)

有一种特殊类型的消息调用,被称为 委托调用(delegatecall) 。它和一般的消息调用的区别在于,目标地址的代码将在发起调用的合约的上下文中执行,并且msg.sender 和msg.value 不变。 这意味着一个合约可以在运行时从另外一个地址动态加载代码。存储、当前地址和余额都指向发起调用的合约,只有代码是从被调用地址获取的。 这使得 Solidity 可以实现”库“能力:可复用的代码库可以放在一个合约的存储上,如用来实现复杂的数据结构的库。

4. CREATE 指令(CREATE instruction)

另一个与合约调用相关的是调用指令集的时候使用CREATE指令。这个指令将会创建一个新的合约并生成新的地址。与以太坊的创建唯一的不同在于波场新生成的地址使用的是传入的本次智能合约交易id与调用的nonce的哈希组合。和以太坊不同,这个nonce的定义为本次根调用开始创建的合约序号。即如果有多次的 CREATE指令调用,从1开始,顺序编号每次调用的合约。详细请参考代码。还需注意,与deploycontract的grpc调用创建合约不同,CREATE的合约并不会保存合约的abi。

5. 内置功能属性及内置函数 (Odyssey-v3.1.1及之后的版本暂时不支持TVM内置函数)

1)TVM兼容solidity语言的转账形式,包括:

  • 伴随constructor调用转账
  • 伴随合约内部函数调用转账
  • transfer/send/call/callcode/delegatecall函数调用转账
    2)不同账户为超级节点投票 (Odyssey-v3.1.1及之后的版本暂时不支持)
    3)超级节点获取所有奖励 (Odyssey-v3.1.1及之后的版本暂时不支持)
    4)超级节点通过或否定提案 (Odyssey-v3.1.1及之后的版本暂时不支持)
    5)超级节点提出提案 (Odyssey-v3.1.1及之后的版本暂时不支持)
    6)超级节点删除提案 (Odyssey-v3.1.1及之后的版本暂时不支持)
    7)波场byte地址转换为solidity地址 (Odyssey-v3.1.1及之后的版本暂时不支持)
    8)波场string地址转换为solidity地址 (Odyssey-v3.1.1及之后的版本暂时不支持)
    9)向目标账户地址发送token转账 (Odyssey-v3.1.1及之后的版本暂时不支持)
    10)查询目标账户地址的指定token的数量 (Odyssey-v3.1.1及之后的版本暂时不支持)
    11)兼容所有以太坊内置函数

注意:2)- 10)为波场自己的内置函数 (Odyssey-v3.1.1及之后的版本暂时不支持TVM内置函数)

以太坊 RIPEMD160 函数不推荐使用,波场返回的是一个自己的基于sha256的hash结果,并不是准确的以太坊RIPEMD160。以后会考虑删除这个函数。