我想从账户A在以太坊进行交易,但交易费用应该从账户B支付。 在以太坊中可能吗?
目前,没有任何内置条款允许其他用户支付特定交易的汽油费。但是,通过向用户退款来支付汽油费的合同的概念存在并且可以实施。当然,这开启了攻击此功能以耗尽资金的可能性。
这里正在进行关于未来版本(Serenity(的讨论,该版本可以解决仅发送交易的帐户支付费用的概念。
以太坊中没有对该功能的内置支持。但是有一种流行的方法来解决这个问题,称为加油站网络,又名GSN。 OpenGSN(https://opengsn.org/(提供了一个实现。 要快速掌握这个想法,请阅读(现已弃用(https://docs.openzeppelin.com/learn/sending-gasless-transactions
让我引用OZ文档中的相关部分:
这是一个简单想法的花哨名称:第三方(称为 中继器(可以发送其他用户的交易并支付自己 汽油成本。在此方案中,用户对消息进行签名(而不是事务( 包含有关他们想要执行的交易的信息。 然后,中继器负责签署有效的以太坊交易 有了这些信息并将它们发送到网络,支付 汽油成本。基本协定保留用户的身份 最初请求交易。通过这种方式,用户可以进行交互 直接使用智能合约,无需钱包或拥有 醚。
这意味着,为了支持您的元交易 应用程序,您需要保持中继器进程运行 - 或利用 一个分散的中继器网络。
不,gas始终由发送交易的帐户支付。
以太坊网络中没有原生支持。
然而,这个特殊问题已经被积极讨论了一段时间。
尽管上面的问题主要讨论了account B
为account A
进行代币转移以及为account B
赚取一些代币作为费用。
用户甚至在 http://lavawallet.io 提到了一个完整的工作示例
截至目前,可以使用Permit
功能。这种交易也称为gasless transaction
。
使用 erc20 为了发送代币,我们必须首先批准交易以允许地址转移,然后我们调用transferFrom
. 有了 permit,我们将只调用一个函数,而不是调用两个函数。
对于无气体交易,我们将在链下签署交易,这样我们就不会支付任何气体费用。然后我们将签名的v,r,s
发送到 Allow 函数,经过一些检查,如果我们通过了所有检查,permit()
将调用approve
到交易,然后 spender 将能够执行交易。
这是来自Uniswap ERC721Permit.sol
function permit(address spender,uint256 tokenId,uint256 deadline,uint8 v,bytes32 r,bytes32 s
) external payable override {
// set a deadline for the transaction
require(_blockTimestamp() <= deadline, 'Permit expired');
bytes32 digest =
keccak256(
abi.encodePacked(
'x19x01',
// DOMAIN_SEPARATOR a hash value that calculated to ensure uniquness of the signature
DOMAIN_SEPARATOR(),
keccak256(abi.encode(PERMIT_TYPEHASH, spender, tokenId, _getAndIncrementNonce(tokenId), deadline))
)
);
address owner = ownerOf(tokenId);
require(spender != owner, 'ERC721Permit: approval to current owner');
// this function uses assembly extcodesize func to check if the adddress is a contract
if (Address.isContract(owner)) {
require(IERC1271(owner).isValidSignature(digest, abi.encodePacked(r, s, v)) == 0x1626ba7e, 'Unauthorized');
} else {
address recoveredAddress = ecrecover(digest, v, r, s);
require(recoveredAddress != address(0), 'Invalid signature');
require(recoveredAddress == owner, 'Unauthorized');
}
// after passing all the checks,we approve the spender to transfer the token
_approve(spender, tokenId);
}
}
您可以阅读 EIP712
这只有在钱包是合约时才能完成。 一般来说,有两种类型的帐户
- 使用私钥的帐户(普通钱包(
- 没有私钥的账户(合约钱包(
我们可以通过合约地址,用户存款来实现您的目标,并且可以做任何事情,以后如果我们想进行提款或转账的交易,用户支付交易费用,结果资金从合约钱包转移到其他钱包。