如果智能合约存储在区块链中的区块上,其状态如何更新?

问题描述

我知道智能合约被转换成字节码并存储在区块链中的一个块上。可以类似于 Kickstarter 使用智能合约。项目团队可能会设定一个资金目标,只有在支持者捐赠足够的资金来实现目标时才会支付。

但是智能合约如何知道何时向项目团队付款?一个区块的哈希值会根据其数据发生剧烈变化。因此,跟踪一个区块内的捐赠金额和交易 ID 应该是不可能的,因为它会改变区块的哈希值。因此,智能合约如何知道已经资助了多少钱,如果没有达到资助目标,它如何记住将钱捐赠到哪里?

真的有分类帐(或区块链)和状态数据库吗? 如果是这样,我假设我们将与智能合约关联的值存储在状态数据库中。

解决方法

智能合约的字节码在交易中发布(在区块中挖掘),然后存储在与地址相关联的网络(通常是以太坊或币安智能链)的存储中。

因此,每次与智能合约交互时,您都在与一个地址交互,该地址与包含字节码的存储块相关联。加上字节码指向其他存储槽,其中存储了其变量的值。

所有状态变化(包括存储值的变化)都是账本数据库的一部分。原始区块链数据仅包含状态更改(不是当前状态),但大多数更高层默认返回当前状态(您仍然可以选择获取旧状态,例如“defaultBlock”参数 here)。有些层甚至不允许访问以前的状态(例如用于编写智能合约的 Solidity 和 Vyper 语言 - 您可以将此代码编译为字节码)。


但是智能合约如何知道何时向项目团队付款?

智能合约可以访问任何地址的当前余额,包括它自己的。它还可以有一个包含资金目标的变量。比较这两个值可以告诉您是否达到了目标以及智能合约是否应该向项目团队付款。

但是,智能合约目前没有任何本地计时器(例如 cronjobs)或事件处理程序 - 并且在将交易发送到智能合约的地址(交易的 data 字段)之后执行函数说明您要执行的函数以及传递的参数)。

因此您需要手动发送交易(执行 withdraw() 函数)或使用一些链下工具(可以查看当前余额,然后为您发送执行该函数的交易)。

pragma solidity ^0.8;

contract MyContract {
    uint256 constant FUNDING_GOAL = 1 ether;
    address constant TEAM_ADDRESS = address(0x123);

    /**
     * Throws if the current balance is lower than the goal
     * Otherwise sends all of the current balance to the predefined address
     *
     * Need to send transaction with correct value of the `data` field
     * to execute this `withdraw()` function.
     * Most client apps generate the correct value of `data` field for you
     * after selecting the function name and specifying argument values.
     */
    function withdraw() external {
        require(address(this).balance >= FUNDING_GOAL,'Haven\'t reached the funding goal');
        payable(TEAM_ADDRESS).transfer(address(this).balance);
    }
    
    /**
     * Allows this contract to receive native currency of the network (usually ETH or BNB)
     */
    receive() external payable {}
}