-
Notifications
You must be signed in to change notification settings - Fork 245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Meta Txs: Adding support for meta transactions in aragon apps (Part 1) #526
base: next
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More than comments I left a bunch of questions, I'm afraid I'm not fully getting it 😅
Besides, about the volatile storage, I think the initial idea was counting on EIP 1283, which I think didn't get in because of that re-entrancy issue, so it seems we are not going to save those 10k extra gas.
Thanks for your review @bingen! Although, I think it is more interesting to review directly the last approach we decided to follow :) |
@izqui I've decided to drop the idea of calculating the amount of gas to be refunded to the off-chain service since it was actually taking a lot of gas to perform such calculation (I reached an overload of 100k gas for some edge cases). That said, I came up with the idea of delegating the decision of calculating the gas refund to the DAOs' members. Note that off-chain services can tell whether the submitted amount of gas actually covers the costs of a transaction before relaying it. Therefore, DAOs' members will be incentivized to estimate gas values correctly. To achieve this, I propose using a monthly quota on the relayer side to limit the amount of txs users can relay. And ofc, this triggers some new questions we should discuss:
|
This could be an issue if the 'service provider' can relay their own transactions (and in the current implementation it seems like any account can use the relayer), as their incentive would be to use a high gas limit/price.
I think we should, as the amount of activity that happens in the organization will change over time and the gas price can fluctuate.
I don't think this is really important if the amount can be changed.
I think that having a unique quota amount for everyone should be fine for a first version.
I'd say the off-chain service should make sure that the transaction won't revert. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of aspects that we should think about:
-
Should the Relayer only perform calls to other apps in the same DAO that it is installed in? Detecting whether an app is installed in a given DAO cannot be done on-chain, but we could check whether the
to
address is either the Kernel orAragonApp(to).kernel()
is the Kernel of the DAO. -
Right now, the Relayer can relay actions signed by any
from
account. We should implement some sort of authorization mechanism (using the ACL?) so the relayer only relays calls from authorized accounts. We should also look into supporting immediate forwarders like the Token Manager (see Proposal: add forwardWillExecuteImmediately() to Forwarder interface #521) as it is the way that 'membership' is managed in most organizations.
@izqui I already addressed your comments, feel free to take another look :) PS: The CI coverage task is failing since |
c85ed73
to
2759f3b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome job! The signer address append to calldata is pretty neat!!!
// Constant values used to identify the domain for the current app following EIP 712 spec | ||
string private constant EIP_712_DOMAIN_NAME = "Aragon Relayer"; | ||
string private constant EIP_712_DOMAIN_VERSION = "1"; | ||
uint256 private constant EIP_712_DOMAIN_CHAIN_ID = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this could be passed in the constructor, or have a setter, to be able to be used in test chains?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want to do that to avoid loading from storage these values every time we need to verify a signature. WDYT?
contracts/relayer/Relayer.sol
Outdated
uint256 internal monthlyRefundQuota; | ||
|
||
// Mapping that indicates whether a given address is allowed to use the relay service | ||
mapping (address => bool) internal allowedSenders; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having to store all possible senders in this mapping looks like too much overhead, specially for big organizations, which probably already have a list of members, or a group of authorized senders.
I guess this should be an ACL, but I wonder if Forwarding mechanism (in order to use Token Manager, which seems a likely option) would work with this setup.
Another option (I don't really like the use of Token Manager as a group) would be some kind of interface IGroup
which implements a belongs(member, group)
function, which I actually think should be part of the ACL
, but this looks way out of the scope of this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially we did, but given that using the ACL
increases gas costs in ~15k
, we decided to use it but in a more "async" way. As you can see, we are using it to edit the whitelist of allowed senders, but avoiding it when we need to check if someone is in included in the list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, then I think this works for services, as I don't expect having so many, but imagine Aragon wants to subsidize some voting (or whatever) to all token holders. According to etherscan, that would be like ~21k holders, i.e., allowed senders. Adding them to that mapping would be quite an amount of gas (and there will probably be bigger orgs with this problem), besides we should monitor ANT transactions to edit allowances.
If we used such an IGroup
interface, we could have Token Manager implementing it, or if we don't want to update it, just have a wrapper small contract implementing which would get the balance and return true if > 0
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, having groups would be amazing :)
mapping (address => bool) internal allowedSenders; | ||
|
||
// Mapping that indicates whether a given address is allowed as off-chain service to relay transactions | ||
mapping (address => bool) internal allowedServices; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be an ACL role too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explained above
returns (bool) | ||
{ | ||
bytes32 messageHash = _messageHash(to, nonce, data, gasRefund, gasPrice); | ||
address signer = messageHash.recover(signature); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't toEthSignedMessageHash
needed here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, that's the idea of supporting EIP 712 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it may be related to it, but didn't read all the details of that EIP, and I was confused by the fact that toEthSignedMessageHash
is still in ECDSA lib. Do we need it there then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really, it is part of the library I picked from OpenZeppelin
The main idea of this PR is to add support for meta transactions to allow any member of a DAO to interact with its apps without having funds necessarily.
I've also started working on the off-chain functionality for the corresponding service here.
Approach
The main idea is to have shared trusted off-chain service in charge of submitting the transactions to an on-chain relayer that will be in charged of signature validation, nonce validation, and will forward these transactions to the target app if all the verifications passed. The off-chain service will get refunded by the on-chain relayer for every transaction it relays. This will allow every to manage and customize their own relayers as they want.
The following table shows the different costs added per transaction to support this approach:
Among other things, the total gas overload for a relayed transaction is ~53k of gas
Other approaches investigated
I've been exploring other approaches for this topic based on the same concept of having a shared trusted off-chain service in charge of submitting the transactions on-chain that will get refunded by the DAOs for every transaction it relays to make sure it doesn't run out of funds. The different alternatives explored are the possible combinations between the following patterns:
AragonApp
itself.