> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blockx.chaintable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 编写 EVM 数据函数

> 在明确的区块查询合约，并生成保持精度的派生值。

使用函数将 EVM 状态或事件输入转换为派生记录。本例查询代币余额，并在输出中携带读取上下文。

## 链与区块上下文

提供节点后端支持的链、具体区块标识、代币合约和持有人地址。所选区块必须可由后端提供。`EVM(chain_id, block_id)` 将该对象的状态读取与合约查询绑定到此上下文。

## 前置条件

* 已接入 EVM 节点访问的 BlockX 执行环境。
* 在所选区块实现 `balanceOf(address)(uint256)` 的合约。
* 与 BlockX checkout 的 `python/pyproject.toml` 一致的函数依赖。

## 编写函数

```python theme={null}
def _(chain_id, block_id, token, holder):
    from leafage import EVM

    evm = EVM(chain_id, block_id)
    balance = evm.call(token, "balanceOf(address)(uint256)", [holder])
    return {
        "id": holder,
        "chain_id": chain_id,
        "block_id": block_id,
        "token": token,
        "balance": balance,
    }
```

保持 `balance` 为整数。需要写表时，准备兼容的目标列；表 Writer 会按目标 schema 投影返回记录。

## 提交参数

一次性计算时，将 `[chain_id, block_id, token, holder]` 放入 `InputsCallConfig.callList` 的一行，并使用 `ReturnValueHandler`。提交方式见[一次性计算](/zh/guides/run-once)。

按触发表计算时，根据源 schema 组装这些参数。处理历史数据时，传入每行对应的区块上下文；选择 bundle 不会将所有行的依赖读取绑定到同一个历史区块。

## 确认结果

检查任务成功，并核对返回记录中的 `balance`、`block_id` 和 `token`。返回值确认这组参数的计算结果；只有选择表 Writer Plugin 时才会写表。

## 处理失败

| 现象 | 检查项 |
| - | - |
| 区块不可用 | 后端是否提供所选链与历史区块 |
| 合约调用回退或解码失败 | 合约地址、方法签名、参数与区块 |
| 函数被拒绝 | 支持的 import 与审计结果 |
| 历史值不符合预期 | 显式传给函数的区块 |

## 继续阅读

* [EVM 计算模型](/zh/concepts/evm-computation)
* [按区块计算](/zh/guides/block-computation)
* [同步调用与调试](/zh/guides/synchronous-invocation)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.