You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
To promote adoption, many dapps could create blockchain accounts for their users, but without giving them an initial balance (maybe, the dapp could give them some tokens). Then, these users want to interact with the blockchain, to do actions (ie play a game). This proposal describes a way to allow these users to execute actions in the blockchain, without having an available balance to cover the gas costs. Also, it allows them to pay (if needed) that gas cost using their tokens.
Description
In order to solve these use cases, we could use the concept of Ethereum meta transactions (alone, or using Gas Station Network). But that approach has a issue: the contracts to call should be aware that the msg.sender used in those final transaction don't correspond to the original user. This issue also makes difficult to transfer tokens to pay the execution of transactions (usually, the owners SHOULD send such transaction, but in these use cases, they don't not have any available balance).
So, in this proposal is based in a new pre-compiled contract, that given the description of the original sender actions, executes them as such sender, but the gas costs are paid by another account, the sponsor account. Optionally, this sponsor account could receive a payment in tokens from the original sender.
For improved security, the new pre compiled contract could be called only from an external transaction. To improve security, this precompiled contract could be call only from transactions, not via internal message (ie Solidity call or an EVM call). Even in the case the precompiled contract could be invoked internally, the sender nonce is checked, given a quick failure notice.
Detailed Description
The sender is A, without balance. A wants to execute a transaction invoking a smart contract. Then, A declares his/her intentions:
Receiver account to invoke (the smart contract address)
Value to send (possibly 0)
Data to be used
A could declares more than one triplet. After declaring them, A signs the message with contains the list of intentions AND the next sender nonce, to endorse with his/her key that the intentions will be not repudiated.
The proposed format is: intentions, but to discuss if transaction format is needed for hardware wallets interaction (apparently it is not mandatory)
At the execution of intentions, the sender nonce will be incremented using the nonce provided. Transaction validation should check that sponsor nonce is right, AND that the provided (and signed) sender nonce is also right. The recommended logic for sponsor is to DON'T accept advances nonce from a sender, because in this case, it is harder to check the availability of resources to execute anything (ie, the availability of tokens, if the sponsor requires token payments).
The signed messages (intentions triples and sender nonce) are sent to an sponsor S application (possible a public exposed API), with optional fields: the gas cost estimated for all operations, the suggested gas price (it's up to the dapp how to decide this values, but the straight way is to use the estimated gas JSON RPC for normal transactions). The sponsor logic checks the valid signature, could examine the intentions, could accept or change the gas price (if sponsor accepts token payments, could check suggested gas price with tokens provided), and approve the intentions. Then, S builds a valid blockchain transaction:
Sender: sponsor S
Receiver: the dedicated pre compiled contract C
Nonce: sponsor nonce
Value: any additional value needed, if the inner intentions have values > 0
Data: the signed intentions plus sender nonce payload
Gas and Gas Price: determined by sponsor logic, according to sender estimation
S signs this transaction T and send it to the blockchain. The transaction hash is informed to the sender A. In this way, A could verify the existence of the transaction in the blockchain, and its result.
The transaction T is a normal transaction. To the rest of the logic, it does not involves consensus or validation changes. Except that it needs the existence of a new pre compiled contract C
When transaction T is executed (in miner logic, or in other nodes), the usual logic is applied: it invokes a contract, and the gas used * gas price will be pay by the sender (the sponsor S). The key logic is in the pre compiled contract C:
It verifies the payload (triple list, sender nonce and signature), and then, it starts to execute each intention, using internal message to call for each intention:
-- Sender: the original sender (identified by the payload signature)
-- Receiver: the receiver of the intention under process
-- Value: the value of the intention under process
-- Data: the data of the intention under process
At the end of transaction execution, gas costs are covered by the sponsor S account, as usual in other transactions: the sender pays.
If one the internal message execution is reverted, all the full sponsor transaction is reverted.
Use Cases
Promote Game Adoption
A Dapp exposes a game experience (ie spaceship battles) using the web, but recording player moves and items into the blockchain. To have an easy onboarding, each new user is assigned with a blockchain account, without balance. When the user plays a move, the dapp construct the intention (invocation to the game contract) and sends this information to the sponsor site (maybe a public API). Sponsor logic checks_
Receiver is the game contract
The move in valid
etc
and then the sponsor builds, sends and pays the blockchain transaction. The game is promoted, so the business model covers the gas costs. The original user don't need to pay in anyway to the sponsor.
Social Network
A social network wants to reward their users by their activities, and gives them some utility tokens. When the user wants to exchange this tokens, or do any action in the blockchain, he/she could pay with such tokens the execution of transaction (usually the user has no available balance). The social network browser logic (like a dapp) builds the user intention. In this case, the intentions are two:
Pay with n tokens to sponsor
Play a game
The signed intentions are sent to the sponsor site/logic. The sponsor validates that the amount of tokens is available, and that it is enough to cover the total gas costs. If sponsor S accepts the intentions, it builds the blockchain transaction, with receiver the dedicated pre compiled smart contract.
Out of scope
To discuss detailed sponsor check logic. Also, to solve any possible attack to sponsor (we could leverage the current solutions and proposals, for Ethereum, relayers in Gas Station Network, and meta transactions in general).
Implementing the solution
Only a simple pre compiled contract is needed. The current code allows to build this extension, as a hard fork, using a bounded effort, and complying with time to market.
Intentions are executed as internal calls. The gas costs added is the internal call cost. The gas limit to provide, is the current gas limit BEFORE the internal call, using current RSK behavior for internal call (AFAIR there is a rule to pass a bit less gas limit).
The total gas cost is the internal call gas costs (including the called code gas cost), check the result (if false revert), check sender signature, and the transaction (invoke and payload) cost.
The format of the message to receive as payload:
RLP encoded (it's better than ABI to represent hierachical heterogeneus data)
Three items: a list, a two single items. The first single item is the sender nonce. The second single item is the sender signature as bytes
The list item has items that are list. Each item has three subitems: receiver address, value, data (array of bytes)
The message to sign is a list with the above first two items: list of intentions, and sender nonce. Alternative: the hash of that message could be signed. Alternative: a message compatible with EIP 712 could be signed (having a domain identification, ie, the precompiled contract C address)
All the specification allows the change of format is needed or if there are other format more appropiate for lower payload gas cost, o easiness for dapps. The key things are in place: list of intentions (triples), sender nonce, sender signature.
Some special cases to cover:
Allows trace_transaction gets the appropriate information about internal calls and transfers
The same for debug_transaction
As mentioned, some logic it's up to dapp and sponsor logic, like the negotiation of gas limit and gas price to use. If it is really needed, each triple could an additional gas limit (being then a quadruplet), but having sponsor checked the current status of the blockchain and checked the full gas limit, this additional field could be not needed.
The use of the sender nonce (signed after the list of intentions) is to avoid replay the same intentions by the same or different sponsor. Also it could disallow sender sending the same intentions to different sponsors: only one will be accepted and executed if they share the same sender nonce.
DApp and Sponsor Logic
Along this proposal, the logic for sponsor and dapp was mentioned, but it is only a recommendation, to avoid some rogue behavior from dapp or sponsor. I think that a detailed logic could be specified in a separate proposal, and even could be relative to the real use case. Ie, it the real use case is to have initially ONLY one kind of sponsor, for a social network, and only one dapp, more specific logic could be applied. An example: in that case, the sponsor could check that the sender account corresponds to a social network user account, and enforce that existence, even when the blockchain account still does not exist in the blockchain.
Some recommendations:
The sponsor should check and recalculate the gas needed even if the sender specifies it
In case of token payments, the sponsor should evaluate the gas price to pay according to his/her valuation of token given.
In case of payment with tokens, the intention declares the sponsor payment account as the receiver of the token transfer. So, they cannot be stolen by other sponsor.
It is recommended that sponsor use many accounts to sign the final transactions, in order to avoid his/her nonce could be a bottleneck in the advance of the operations
Senders could send the same intentions (except token payment if any) to different sponsor. But if they use the same nonce, only one final transaction will be executed. If they use different nonce, maybe both are executed, in predetermined order, according to senders instructions
Signing only intentions with sender nonce according to the next nonce to use by the sender, enforces sponsor logic to be sure that the resources are available (maybe after invoking a test transaction using estimate gas JSON RPC entry point).
Exiting the solution
In case it is needed, the sponsors could stop to accept intentions at any moment. And the pre compiled contract could be suspended (with a hard fork at heigh H).
The text was updated successfully, but these errors were encountered:
The specification suggests that the payload format is:
payload = (nonce,signature, (list_of_intentions) )
where
list_of_intentions = list of (receiver address, value, data)
What does the signature signs ? There are several possibilities. I think you mean the payload but replacing the signature by something else. It is the empty field?
The use of the account nonce in a non-free transaction brings several problems regarding mempool.
One can think of an attack where the attacker fills the mempool with a huge transaction (and the network propagates it) but the attacker cancels it with a single call to the precompiled contract, where the call was hidden in another previous transaction in the block, under multiple recursive calls ?
To be more clear, both the call to the precompile and the free-transaction call share the same nonce.
This attack can be repeated with hundreds of accounts simultaneously, as a DoS attack to miners and the network.
That's why Patrick McCorry's proposal uses a different nonce queue.
Motivation
To promote adoption, many dapps could create blockchain accounts for their users, but without giving them an initial balance (maybe, the dapp could give them some tokens). Then, these users want to interact with the blockchain, to do actions (ie play a game). This proposal describes a way to allow these users to execute actions in the blockchain, without having an available balance to cover the gas costs. Also, it allows them to pay (if needed) that gas cost using their tokens.
Description
In order to solve these use cases, we could use the concept of Ethereum meta transactions (alone, or using Gas Station Network). But that approach has a issue: the contracts to call should be aware that the
msg.sender
used in those final transaction don't correspond to the original user. This issue also makes difficult to transfer tokens to pay the execution of transactions (usually, the owners SHOULD send such transaction, but in these use cases, they don't not have any available balance).So, in this proposal is based in a new pre-compiled contract, that given the description of the original sender actions, executes them as such sender, but the gas costs are paid by another account, the sponsor account. Optionally, this sponsor account could receive a payment in tokens from the original sender.
For improved security, the new pre compiled contract could be called only from an external transaction. To improve security, this precompiled contract could be call only from transactions, not via internal message (ie Solidity call or an EVM call). Even in the case the precompiled contract could be invoked internally, the sender nonce is checked, given a quick failure notice.
Detailed Description
The sender is A, without balance. A wants to execute a transaction invoking a smart contract. Then, A declares his/her intentions:
A could declares more than one triplet. After declaring them, A signs the message with contains the list of intentions AND the next sender nonce, to endorse with his/her key that the intentions will be not repudiated.
The proposed format is: intentions, but to discuss if transaction format is needed for hardware wallets interaction (apparently it is not mandatory)
At the execution of intentions, the sender nonce will be incremented using the nonce provided. Transaction validation should check that sponsor nonce is right, AND that the provided (and signed) sender nonce is also right. The recommended logic for sponsor is to DON'T accept advances nonce from a sender, because in this case, it is harder to check the availability of resources to execute anything (ie, the availability of tokens, if the sponsor requires token payments).
The signed messages (intentions triples and sender nonce) are sent to an sponsor S application (possible a public exposed API), with optional fields: the gas cost estimated for all operations, the suggested gas price (it's up to the dapp how to decide this values, but the straight way is to use the estimated gas JSON RPC for normal transactions). The sponsor logic checks the valid signature, could examine the intentions, could accept or change the gas price (if sponsor accepts token payments, could check suggested gas price with tokens provided), and approve the intentions. Then, S builds a valid blockchain transaction:
S signs this transaction T and send it to the blockchain. The transaction hash is informed to the sender A. In this way, A could verify the existence of the transaction in the blockchain, and its result.
The transaction T is a normal transaction. To the rest of the logic, it does not involves consensus or validation changes. Except that it needs the existence of a new pre compiled contract C
When transaction T is executed (in miner logic, or in other nodes), the usual logic is applied: it invokes a contract, and the gas used * gas price will be pay by the sender (the sponsor S). The key logic is in the pre compiled contract C:
-- Sender: the original sender (identified by the payload signature)
-- Receiver: the receiver of the intention under process
-- Value: the value of the intention under process
-- Data: the data of the intention under process
At the end of transaction execution, gas costs are covered by the sponsor S account, as usual in other transactions: the sender pays.
If one the internal message execution is reverted, all the full sponsor transaction is reverted.
Use Cases
Promote Game Adoption
A Dapp exposes a game experience (ie spaceship battles) using the web, but recording player moves and items into the blockchain. To have an easy onboarding, each new user is assigned with a blockchain account, without balance. When the user plays a move, the dapp construct the intention (invocation to the game contract) and sends this information to the sponsor site (maybe a public API). Sponsor logic checks_
and then the sponsor builds, sends and pays the blockchain transaction. The game is promoted, so the business model covers the gas costs. The original user don't need to pay in anyway to the sponsor.
Social Network
A social network wants to reward their users by their activities, and gives them some utility tokens. When the user wants to exchange this tokens, or do any action in the blockchain, he/she could pay with such tokens the execution of transaction (usually the user has no available balance). The social network browser logic (like a dapp) builds the user intention. In this case, the intentions are two:
The signed intentions are sent to the sponsor site/logic. The sponsor validates that the amount of tokens is available, and that it is enough to cover the total gas costs. If sponsor S accepts the intentions, it builds the blockchain transaction, with receiver the dedicated pre compiled smart contract.
Out of scope
To discuss detailed sponsor check logic. Also, to solve any possible attack to sponsor (we could leverage the current solutions and proposals, for Ethereum, relayers in Gas Station Network, and meta transactions in general).
Implementing the solution
Only a simple pre compiled contract is needed. The current code allows to build this extension, as a hard fork, using a bounded effort, and complying with time to market.
Intentions are executed as internal calls. The gas costs added is the internal call cost. The gas limit to provide, is the current gas limit BEFORE the internal call, using current RSK behavior for internal call (AFAIR there is a rule to pass a bit less gas limit).
The total gas cost is the internal call gas costs (including the called code gas cost), check the result (if false revert), check sender signature, and the transaction (invoke and payload) cost.
The format of the message to receive as payload:
The message to sign is a list with the above first two items: list of intentions, and sender nonce. Alternative: the hash of that message could be signed. Alternative: a message compatible with EIP 712 could be signed (having a domain identification, ie, the precompiled contract C address)
All the specification allows the change of format is needed or if there are other format more appropiate for lower payload gas cost, o easiness for dapps. The key things are in place: list of intentions (triples), sender nonce, sender signature.
Some special cases to cover:
trace_transaction
gets the appropriate information about internal calls and transfersdebug_transaction
As mentioned, some logic it's up to dapp and sponsor logic, like the negotiation of gas limit and gas price to use. If it is really needed, each triple could an additional gas limit (being then a quadruplet), but having sponsor checked the current status of the blockchain and checked the full gas limit, this additional field could be not needed.
The use of the sender nonce (signed after the list of intentions) is to avoid replay the same intentions by the same or different sponsor. Also it could disallow sender sending the same intentions to different sponsors: only one will be accepted and executed if they share the same sender nonce.
DApp and Sponsor Logic
Along this proposal, the logic for sponsor and dapp was mentioned, but it is only a recommendation, to avoid some rogue behavior from dapp or sponsor. I think that a detailed logic could be specified in a separate proposal, and even could be relative to the real use case. Ie, it the real use case is to have initially ONLY one kind of sponsor, for a social network, and only one dapp, more specific logic could be applied. An example: in that case, the sponsor could check that the sender account corresponds to a social network user account, and enforce that existence, even when the blockchain account still does not exist in the blockchain.
Some recommendations:
Exiting the solution
In case it is needed, the sponsors could stop to accept intentions at any moment. And the pre compiled contract could be suspended (with a hard fork at heigh H).
The text was updated successfully, but these errors were encountered: