-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
ERC - Multi-signature standard API for Second Layer Applications #769
Comments
It'd be good to have smart contracts as one of the owners of a multisig standardized as well, or at least queryable if it's supported. Think a multisig being a part owner of another multisig, for instance. |
You know what. I finally figured out what's missing from this. This needs a modifier statement complete with the forwarding of the data from the transaction. This way type safety is also achieved within the solidity process and enables this to be extended to include swapping rules, confirmation rules, etc. There might also be a use for somehow storing all the signatures in memory but that's probably a bit out of scope. |
@stskeeps I can definitely see benefits to mutisigs being owners of other multisigs, but I worry about the complexity that requires. Contracts can't (and to my knowledge won't ever) be able to sign transactions directly. This seems dangerous for a standard, simple multisig approach. @VoR0220 I don't follow. Perhaps it's because I'm unfamiliar with a lot of the new Solidity features. Can you provide an example? As for storing signatures, I agree it could be useful. This scheme does not preclude someone from implementing a contract that does that. Edit: I see I pushed storage of signatures off-chain in the original draft. Technically that is not required so I updated the ERC. |
Though contract may answer whether it has “signed” particular transaction or not. Once contract implements method like |
@alex-miller-0 It's a rather old solidity feature actually and fairly simple. The modifier would look something like the following:
Granted the call part at the end would probably need to be modified, but I think this makes it a tad cleaner and more extensible...also preserves type safety in the original function call. |
@alex-miller-0 one thing I’ve been considering is to make the core logic of verifying the signatures into a stateless library. This would further mimic the stateless nature of bitcoin P2SH. This library would take as inputs the array of owners, the threshold number, as well as the list of signatures. It would return true if the list of signatures is valid and false otherwise. You would still need to create the actual multisig contracts in much the same way except the core would be a call to this library. Such a library, being stateless, could also be a good target for formal verification. |
I would love to see an optional section, or extension EIP that implements variable membership for this system, too. In my mind that's the one thing preventing this from being generally useful for a lot of persistent multisig use-cases. |
@VoR0220
Here In this case
|
@mikhail-vladimirov This is off-topic for the spec, which only defines interface, not implementation. |
This will immediately limit usages of such library to the narrow class of simple n-of-m wallets. I mean there will be impossible to use it in
etc. |
@christianlundkvist Yes I think a static library is a good idea. @Arachnid I see how that might be useful, but I personally would be wary of using a contract where the owners could change and/or I could be booted from ownership. Is a second layer application's ability to facilitate draining and creation of a new multisig insufficient? @VoR0220 Are you just suggesting a modifier instead of the |
@mikhail-vladimirov
Yep, that was my goal with creating @Arachnid The main usecase I had in mind was holding ETH and tokens, in which case switching owners can be achieved by sending the ETH and tokens to a new contract. |
This is really good for those who are satisfied with functionality. The simpler contract is the better contract. The question is whether such limited functionality should become EIP standard or not. |
@alex-miller-0 @christianlundkvist An example would be the multisig that holds the ENS root. Multisigs that correspond to large team wallets also probably don't want to have to change address and migrate all their tokens every time team membership changes. Given that a quorum of participants can move all the funds to a new account, it doesn't seem like a larger risk to allow that same quorum to change the list of participants. I can see an argument for leaving membership changes out of the basic protocol, but some form of functionality would be useful as at least an optional feature - even if the only thing you can do is swap out one member for another without changing the total number or the threshold. |
I like the idea of making that an extension of this and this small portion being the base standard. Modifier being about implementation is kind of like..hrm..I guess what you'd really be arguing for is a standard library implementation? Which I think might be a better way of viewing this than a standard interface (what good does the interface do us if what's in the interface is genuinely broken?) Although...there is a good point made here by @mikhail-vladimirov (also, yes, that's exactly what I was going for re: the modifier), that weights might need to be taken into account and hence there is a good need for this to be abstracted into the interface category. However...perhaps there's a means of doing that via the described extension EIP? Not sure if it is. |
@mikhail-vladimirov Agree. I created this proposal because I think the basic interface should be extremely simple and common across all UIs even if some have additional features. This would make multisig integration easy, which would likely drive use. @Arachnid That is a compelling use case. I don't see any reason it couldn't be extended from the basic protocol but my imagined use case (opening a multisig with friends+family to keep your funds safer) would be much less safe with that functionality. That said, I will remove the portion of the ERC where I say these are read-only variables, since it seems this standard should be more flexible and should just be confined to an execution interface and some metadata. |
I'm beginning to think that we should view this from the point of contract inheritance layers. The point should be to practice inheritance with this being the base layer (should only focus on verifying transactions and the threshold...though that threshold bit might need to be considered further if we have to think for weighting), and then the second layer is where we standardize an interface for the swapping, weighting, adding, removing, etc. The third layer, is the application main logic to be executed under which inherits the above 1-2 layers. |
When talking about sophisticated wallets, I didn't mean that standard should require such complicated scenarios to be supported by all compliant wallets nor that standard should describe such scenarios. I just believe that standard should not make such scenarios impossible. For example your proposal says:
Actual standard has to define exactly how the hash is calculated, because hash calculation has to be implemented in client code and, if we want to have single client that is able to work with all standard-compliant wallets, then all the wallets should calculate hash in the same way. Here we will need to define how nonce is assigned to a transaction and how it is hashed in. Or, we will need to define some other mechanism to prevent signed transaction from being executed multiple times. As for me, mechanism implemented in simple wallet you referred is fine for simple basic wallet, but is too limited to become a standard, because nonce is assigned to a transaction at the moment the transaction is being executed, but owners need to know nonce when they are signing the transaction, i.e. prior to execution. This makes it really hard to collect signatures for several transactions in parallel assuming some of the transactions may not be able to collect enough signatures and will never be executed. So I think that while general idea is really good, standard should define more flexible mechanism for preventing transaction re-execution and unfortunately it seems that such better mechanism will require signature of |
No, I'm just pointing out that modifiers aren't part of the ABI.
I don't follow - why would your example be less safe with that functionality?
That's also out of scope for an interface specification. Bear in mind implementations may not even be implemented in Solidity.
Personally, I don't think this is a barrier to common multisig wallet use-cases. |
I just meant it adds complexity and requires additional state/changes, which I view as generally less safe. My language was a little stronger than it should have been; I think it's fine as an option just not as a requirement. |
@Arachnid I'm not sure if it is out of scope. Unless my usage of inheritance being specified was too strong, then I can see that as being out of scope. However, I guess my main point is that I'm agreeing with the sentiment that the interfaces ought to be separate, one for basic usage, and another meant to be coupled with the basic usage that carries the standard swap, remove, add functions. Also re: modifiers...got it. 👍 |
Related #745 |
@naumenkogs because a multisig is useful for more than just handling transactions. It's in the name. It's made to do something when multiple signatures create a quorum. Furthermore...this is very easy to extend. It can literally handle anything that you throw at it. Any kind of call, any kind of data, any value...anything. |
I would argue the reverse: Unless you have a good reason that actions (or anything else) have to be stored onchain, don't. |
@naumenkogs I would say that you could practice inheritance here and execute from there. Wrt to the payload issue, if you're going to be performing an external message call, why wouldn't you prepare the payload based off the function you intend to call from the multisig ala the example above using the |
hello people of 2017! i come from the far future. it's 2020. we're all in quarantine from a global pandemic. the british are going through something called "megxit." https://blog.gridplus.io/building-a-usable-multisig-wallet-59039b60cbf6 is still not a thing. |
There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review. |
This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment. |
ERC - Multisignature Standard API for Second Layer Applications
This ERC defines a standardized API for interacting with a multi-signature account contract. This aims to be the smallest amount of functionality required to operate a multisig contract on Ethereum and is meant to be applied to second layer applications (e.g. wallets).
API
A standard multisig contract is deployed based on Christian Lundkvist's design, which I have slightly modified here.
There are two parts to the API:
Note: this is meant to a very generic API containing only the necessary metadata and an execution interface. It was written with the contract linked above in mind, but it should be extendable to cover other use cases.
Public Variables
The above mapping is needed to evaluate if a signer of a message is indeed an authorized
signer of the contract.
Together, these two variables allow the application to query the owners of the contract (for display purposes).
A nonce is required to prevent replay attacks. It is incremented after each successful transaction
execution. It must be used when forming transactions (see #197).
This is the number of signatures required to execute a given message. Note that some contracts
may reject transactions containing more than
threshold
signatures, so it is best to treatthis as the exact number needed.
Execution
Given a set of signatures, a transaction may be executed using the following function:
Where
destination
,value
, anddata
are hashed with additional data following #197. This hash is used in an ECDSA signature to producev
,r
, ands
parameters for each co-signer.Rationale
Recent events have cast Ethereum multisig patterns into the spotlight. Since 2012 Bitcoin has used a standardized pay to script hash (P2SH) multisig pattern which still has no documented exploitations. The relative safety of Bitcon's pattern is likely a result of its extremely small attack surface.
Multisig contracts are critical pieces of infrastructure in the crypto world because they remove single points of failure. There are many potential Ethereum users who would feel much safer with a multisig setup, but are unable to utilize one because many common tools and wallets don't offer multisig support. Although many multisig implementations exist on Ethereum today, they do not share a common API and require more functionality and complexity than many users would want.
The purpose of this standard is to define a common, simple interface that facilitates multisig support in second layer applications like wallets. Setting up a basic multisig wallet with friends or family members should be as easy as pasting a few addresses and clicking a button.
Note: This scheme is agnostic to how signatures are stored. They could either be aggregated by one of the co-signers (i.e. stored on a sever or passed around via a messaging protocol) or they could be temporarily stored in the contract.
The text was updated successfully, but these errors were encountered: