EVM 合约
EVM合约是聪网智能合约的一种执行类型。EVM执行Solidity/EVM状态机,聪网UTXO模型负责真实资产来源和资产结算。
EVM合约遵循智能合约的通用协议。本文只定义EVM合约特有规则。
合约类型
EVM合约类型为:
ContractTypeEVMEVM合约兼容EVM执行语义、ABI、Solidity开发模型和EVM事件模型,但不采用以太坊账户资产模型。EVM合约内部状态可以维护应用账本,真实资产余额以合约地址UTXO集合为准。
地址规则
EVM内部地址保持20字节,以兼容Solidity和ABI。
msg.sender是20字节EVM地址。address(this)是20字节EVM合约地址。event topic中的indexed address按EVM ABI编码。
CREATE和CREATE2生成20字节EVM合约地址。
聪网外部合约地址使用:
ca/tc + version + ContractTypeEVM + hashEVM合约地址hash为20字节EVM地址。EVM内部20字节地址和聪网外部ca/tc地址必须支持无损转换。
chain id、vm version和code hash不放入地址hash:
chain id由网络和地址前缀区分。
vm version由地址version、type和协议升级规则表达。
code hash由部署交易、合约状态和state root承诺表达。
部署规则
CONTRACT_DEPLOY用于部署EVM合约。
EVM部署payload包含:
init code。
constructor参数。
deployer EVM address。
gas limit。
部署nonce。
部署成功后生成:
20字节EVM合约地址。
聪网
ca/tc合约地址。code hash。
初始storage root。
部署结果必须通过同一区块内的canonical CONTRACT_RESULT记录。
调用规则
CONTRACT_INVOKE用于调用EVM合约。
EVM调用payload包含:
calldata。
gas limit。
call nonce。
调用交易必须输出到被调用合约地址,作为gas/funding输出。被调用合约地址由Call TX输出解析,不写入OP_RETURN。
EVM msg.sender由调用交易最后一个输入的前序输出地址确定,再映射为20字节EVM地址。节点不得从witness公钥推导msg.sender。
EVM合约的默认调用表示向合约地址发起一次空calldata调用。输出中的satoshi作为msg.value,其他资产仍由聪网资产层和预编译资产接口表达。
StateDB和执行器
EVM执行器第一阶段基于go-ethereum core/vm。
实现要求:
不修改EVM opcode语义。
实现聪网自定义StateDB。
StateDB维护storage、code、log和state root。
合约资产由UTXO集合表达,不由EVM account balance表达。
资产规则
资产名称在ABI中按字符串编码,使用聪网资产层AssetName.String()结果。
satoshi资产名称固定为:
第一阶段支持聪网已识别并能以UTXO表达的资产:
satoshi。
ORDX资产。
Runes资产。
BRC20资产。
其他已被聪网资产层识别的资产。
EVM合约内部可以维护ERC20或其他应用层余额。该余额不等同于聪网原生资产余额。需要兑现为聪网资产转移时,合约必须通过资产接口生成Asset Intent,并由CONTRACT_RESULT结算。
预编译资产接口
EVM不能直接花费UTXO,只能生成Asset Intent。底层资产接口通过预编译合约提供。
预编译合约负责:
查询合约UTXO资产状态。
生成资产转移intent。
参与Result TX确定性验证。
第一阶段接口:
assetBalance(contract, assetName)transferAsset(to, assetName, amount)receivedAsset(assetName)
msg.value和balance
msg.value和balancemsg.value表示本次Call TX转入合约地址的satoshi数量。
address.balance返回satoshi余额。address(this).balance表示当前合约地址可支配的satoshi总量,该数值由合约地址UTXO集合统计得到。
多资产余额必须通过预编译合约查询。合约storage中的资产记录如果与UTXO统计不一致,Result TX验证以UTXO资产状态和预编译接口为准。
Gas
EVM保留gas机制。
规则:
opcode gas成本沿用geth。
每个部署和调用必须声明gas limit。
执行超过gas limit时结果为out of gas。
gas费用由调用方承担。
区块存在EVM gas总上限。
gas price第一阶段采用协议固定值。
gas费用使用统一gas资产支付。
gas费用归出块节点。
触发器
EVM合约可以通过协议预编译合约注册高度触发器。触发器记录在EVM状态中,并参与EVM state root。
高度触发器至少包含:
trigger id。
目标合约地址。
触发高度。
触发执行gas limit。
触发时调用的calldata。
出块节点在构造每个区块时必须检查EVM状态中已经到期的触发器。即使候选区块没有普通EVM deploy/invoke交易,只要存在到期触发器,也必须执行触发器并在需要结算时生成canonical CONTRACT_RESULT。
验证节点遇到没有同区块EVM deploy/invoke的EVM Result TX时,必须通过Result TX花费的EVM合约UTXO确定合约地址,并基于上一EVM状态、当前区块高度和区块确认时间重放触发器。触发器不存在、未到期、已被移除、gas limit无效或重放结果不一致时,区块无效。
Result TX和state root
EVM合约不接受外部提交的CONTRACT_RESULT进入mempool。
出块节点执行EVM后,根据Asset Intent构造canonical CONTRACT_RESULT。验证节点独立重放EVM,并比较Result TX和state root。
EVM state root、模版合约state root和Agent合约state root合成统一contract state root,写入coinbase。
Last updated