Root delegations, where the authority field is equal to 0.
Chained delegations, where the authority field is equal to the hash of a delegation whose delegate is the signer of this one.
All delegation chains start with type 1, and all subsequent delegations in a chain are type 2.
Question
Should type 1 delegations work in other positions in the delegation chain?
Example:
Alice signs a type 1 to Bob
Bob signs a type 1 to Carol
Should Carol be able to invoke methods as Alice?
We could also consider this as a new type, "type 3" delegations, where the invoke method is also delegated, and so delegations can be redeemed by the holder.
Considerations
A type 3 delegation could be seen as either a security issue or as a great scalable composibility benefit.
Issue #7 would be likely to introduce this feature/vulnerability inadvertently if done incorrectly.
Pros
Fewer delegation signatures would be needed to maintain a trust graph.
Could enable more spontaneous enablement, if done deliberately.
Cons
Leaking authority from one context into another one can be a form of context collapse, a sort of "mixing the books", and could result in delegations being used in ways they weren't intended.
Examples:
Today, a person issuing an allowance from their own account is strictly issuing access to their own tokens of that type. Those allowances can be delegated too, but can never draw from another user's current balance without an explicit delegation.
With this change, a person could issue hypothetical allowances that could later be backed by someone else issuing them allowances.
Part of this comes down to what is being treated as the "object" of the delegation (in a principle of appropriate boundaries sense): If a user is delegating as much of this contract's authority as they can ever have, then this makes sense. If the contract is itself exposing multiple objects of authority which are conceptually distinct, then it makes sense for each user's delegation chain to always have a distinct root.
This may just be a per-application design decision. Some applications might be ones where the thing managed is simpler, and so flatter delegation graphs make sense, while others are meant to be more granular, and more tightly controlled.
Another example: In a phishing report registry, we might want to accept general "claims of being a phisher", and "claims of trusting other reporters", and in that kind of case maintaining "separate books" seems a bit less critical, and it's more important to have good roots of trust, to build out a great list of phishers.
To implement this behavior, this line would be changed to use _msgSender() instead of msg.sender, and then any invocations could be initiated by anyone delegated rights to this contract by the sender.
Method-restriction caveats could still apply, so I partly think "leaving the system more open ended at the low levels" might be the right choice, and just kinda normalize using method restrictions whenever they might apply.
Summary of current status
There are two types of delegation:
authority
field is equal to0
.authority
field is equal to the hash of a delegation whosedelegate
is the signer of this one.All delegation chains start with type 1, and all subsequent delegations in a chain are type 2.
Question
Should type 1 delegations work in other positions in the delegation chain?
Example:
We could also consider this as a new type, "type 3" delegations, where the
invoke
method is also delegated, and so delegations can be redeemed by the holder.Considerations
A type 3 delegation could be seen as either a security issue or as a great scalable composibility benefit.
Issue #7 would be likely to introduce this feature/vulnerability inadvertently if done incorrectly.
Pros
Cons
Examples:
Part of this comes down to what is being treated as the "object" of the delegation (in a principle of appropriate boundaries sense): If a user is delegating as much of this contract's authority as they can ever have, then this makes sense. If the contract is itself exposing multiple objects of authority which are conceptually distinct, then it makes sense for each user's delegation chain to always have a distinct root.
This may just be a per-application design decision. Some applications might be ones where the thing managed is simpler, and so flatter delegation graphs make sense, while others are meant to be more granular, and more tightly controlled.
Another example: In a phishing report registry, we might want to accept general "claims of being a phisher", and "claims of trusting other reporters", and in that kind of case maintaining "separate books" seems a bit less critical, and it's more important to have good roots of trust, to build out a great list of phishers.
To implement this behavior, this line would be changed to use
_msgSender()
instead ofmsg.sender
, and then any invocations could be initiated by anyone delegated rights to this contract by the sender.Method-restriction caveats could still apply, so I partly think "leaving the system more open ended at the low levels" might be the right choice, and just kinda normalize using method restrictions whenever they might apply.