EIP-2566: 用于合约函数执行的人类可读参数
Authors | Joseph Stockermans (@jstoxrocky) |
---|---|
Created | 2020-03-23 |
Discussion Link | https://ethereum-magicians.org/t/human-readable-parameters-for-contract-function-execution/4154 |
简述
新的以太坊 RPC 方法 eth_sendTransactionToContractFunction
与 eth_sendTransaction
并行,但允许向用户显示人类可读的合约函数执行数据。
摘要
当 dapp 提示用户通过 ProviderWallet 执行智能合约函数时,ProviderWallet 层中显示的确认屏幕无法显示要调用的函数的人类可读详细信息以及要传递的参数。 这是因为用于合约函数执行的以太坊 RPC 方法 (eth_sendTransaction
) 接受的关于调用哪个函数的信息采用非人类可读(且不可恢复)的格式。 因此,当 ProviderWallet 从 dapp 接收到这种非人类可读的信息时,他们无法显示人类可读的版本,因为他们从未收到过,也无法从数据中恢复一个。
这会产生较差且可能危险的用户体验。 例如,恶意 dapp 可能会在 token 合约的 transfer(address,uint256)
函数中替换 address
参数,并将原本打算给其他人的 token 重新路由给自己。 这种障眼法会很隐蔽,并且不太可能被粗略浏览非人类可读数据的普通用户发现。 通过添加一个新的以太坊 RPC 方法 (eth_sendTransactionToContractFunction
) 来接受函数 ABI,ProviderWallet 可以重新创建并向用户显示合约函数执行的人类可读详细信息。
动机
ProviderWallet 定义
像 Metamask 和 Geth 这样的 ProviderWallet 是混合软件,它们将以太坊 API 提供程序与以太坊钱包结合在一起。 这使得他们能够代表用户签署交易,并将这些已签署的交易广播到以太坊网络。 ProviderWallet 的使用既是为了方便,也是为了通过人类可读的确认提示为用户提供的保护。
现有解决方案
过去几年中,关于人类可读以太坊交易数据的话题已经进行了很多讨论。 Aragon 的 Radspec 通过要求合约开发者使用人类可读的注释来修改他们的合约函数来解决这个问题。 然后,ProviderWallet 可以使用 Aragon 的 Radspec 软件从合约代码中解析这些注释并将其显示给最终用户 - 在必要时替换参数值。 不幸的是,这种方法无法用于没有 Radspec 注释的合约(并且可能需要与 IPFS 集成)。
EIP 1138 也直接解决了这个问题,但包含严重的安全问题 - 允许不受信任的 dapp 生成显示给用户的人类可读消息。 在类似的想法中,Geth 的 #2940 PR 和 EIPs 191, 712 都强调了以太坊社区希望 ProviderWallet 更好地告知用户他们实际操作的数据是什么。
最后,ProviderWallet Metamask 已经包含了一些内置的魔法,用于与 ERC20 合约的交互,这允许确认提示显示预期的 token 接收者和 token 值。 尽管这仅针对类似 ERC20 的合约以临时方式完成,但动机是相同的:用户应该获得更好的关于他们依赖 ProviderWallet 执行的合约函数执行的信息。
背景
在某个时候,dapp 会要求用户与合约进行交互。 dapp 和合约之间的交互是以太坊生态系统的重要组成部分,并且通常由 ProviderWallet 充当媒介。 当 dapp 要求用户与合约进行交互时,它将通过将 eth_sendTransaction
方法名称与相关的交易数据一起发送到 ProviderWallet 公开的以太坊 API 来实现。 交易数据的 data
字段包含以太坊虚拟机识别和执行合约函数所需的信息。 该字段具有特定的格式,既非人类可读,也无法恢复到其人类可读状态。
eth_sendTransaction
的 data
字段接受的格式是函数签名的 keccak256 摘要的前四个字节的十六进制编码。 然后,将此缩写哈希与 ABI 编码的函数参数连接起来。 由于函数签名的 keccak256 摘要无法转换回函数签名,因此 data
字段不仅非人类可读,而且也无法恢复。 最重要的是,由于关于其数据类型的信息保存在函数签名原像中,因此对串联参数值的进一步洞察也被进一步混淆。
规范
此 EIP 建议增加以太坊 RPC 方法的集合,以包括一个新方法 - eth_sendTransactionToContractFunction
。 此方法与 eth_sendTransaction
并行,唯一的区别是包含合约函数的 abi
字段。
参数
Object
- 交易对象from
:DATA
, 20 字节 - 发送交易的地址。to
:DATA
, 20 字节 -(创建新合约时可选)交易定向到的地址。gas
:QUANTITY
-(可选,默认值:90000)为交易执行提供的 gas 的整数。 它将返回未使用的 gas。gasPrice
:QUANTITY
-(可选,默认值:待定)用于每次支付的 gas 的 gasPrice 的整数value
:QUANTITY
-(可选)与此交易一起发送的值的整数data
:DATA
- 调用的方法签名和编码参数的哈希值abi
:DATA
- 函数 ABInonce
:QUANTITY
-(可选)nonce 的整数。 这允许覆盖使用相同 nonce 的您自己的待处理交易。
示例参数
params: [{
"from": "0x69e6F1b01f34A702Ce63bA6EF83c64fAEC37a227",
"to": "0xe44127f6fA8A00ee0228730a630fc1F3162C4d52",
"gas": "0x76c0", // 30400
"gasPrice": "0x9184e72a000", // 10000000000000
"value": "0x9184e72a", // 2441406250
"abi": "{
"inputs": [{
"name": "_address",
"type": "address"
}, {
"name": "_value",
"type": "uint256"
}],
"name": "transferTokens",
"outputs": [{
"name": "success",
"type": "bool"
}],
"stateMutability": "nonpayable",
"type": "function"
}",
"data": "0xbec3fa170000000000000000000000006Aa89e52c9a826496A8f311c1a9db62fd477E256000000000000000000000000000000000000000000000000000000174876E800"
}]
返回值 DATA, 32 字节 - 交易哈希,如果交易尚未可用,则为零哈希。
例子 // 请求 curl -X POST –data ‘{“jsonrpc”:”2.0”,”method”:”eth_sendTransactionToContractFunction”,”params”:[{see above}],”id”:1}’
// 结果 { “id”:1, “jsonrpc”: “2.0”, “result”: “0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331” }
理由
此 EIP 提议的 eth_sendTransactionToContractFunction
方法旨在尽可能地与 eth_sendTransaction
并行,因为这两种方法在执行合约函数时都会产生相同的行为。 新引入的 abi
字段是合约 ABI 的一个元素,对应于预期的函数。 data
字段与 eth_sendTransaction
中的 data
字段相同。 abi
字段可以与从 data
字段解析的值组合以重新创建人类可读的合约函数执行信息。
实现
eth_sendTransactionToContractFunction
中的 data
字段与 eth_sendTransaction
所需的字段相同,允许通过用于 eth_sendTransaction
的现有机制完成交易。 输入的参数值可以从 data
字段解析,并且由于我们从 abi
字段知道它们的类型,提供程序钱包可以使用此信息以适当的人类可读格式对值进行编码和显示。 此外,可以使用 abi
字段中提供的信息来重建 data
字段中哈希和截断的函数签名,从而提供额外的检查以确保提供的 ABI 与 data
字段匹配。
向后兼容性
考虑到向后兼容性,此 EIP 建议使用附加方法来扩充以太坊 RPC 方法集,而不是改变现有方法。 添加新 RPC 方法的先例来自 EIP 712,其中建议添加方法 eth_signTypedData
以提高确认提示的安全性。 作为一种替代方法,可以更改 eth_sendTransaction
方法以接受附加的 abi
参数,但这会破坏所有尝试执行合约函数的现有代码。
安全考虑
显示合约地址、函数名称和参数值可以为用户提供额外的安全性,但不能保证函数会按用户期望的方式执行。 实现不佳的合约仍然可以将其函数命名为 transfer
并接受 address
和 uint256
参数 - 但除了合约检查之外,没有任何方法可以让用户知道该合约实际上是一个有效的 ERC20 合约。 此 EIP 并不打算解决围绕信任合约代码的更大问题,而是打算为用户提供更好的工具来准确理解他们广播到以太坊网络的数据中包含的内容。
版权
通过 CC0 放弃版权和相关权利。
Citation
Please cite this document as:
Joseph Stockermans (@jstoxrocky), "EIP-2566: 用于合约函数执行的人类可读参数 [DRAFT]," Ethereum Improvement Proposals, no. 2566, March 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2566.