-
Notifications
You must be signed in to change notification settings - Fork 20
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
Add RepoDriverDataProxy #319
Conversation
687d916
to
b1da02b
Compare
a4a7a70
to
b6cd2f9
Compare
function _callRepoDriver(bytes memory data) internal returns (bytes memory returnData) { | ||
return caller.callAs(_msgSender(), address(repoDriver), data); | ||
} | ||
} |
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.
Mhm, I guess you spend some time thinking about it. Can we find a more elegant solution here?
The flow currently would be:
1. User calls Caller (signature check)
2. Caller calls RepoDriverDataProxy
3. RepoDriverDataProxy is authorized to call back Caller and calls Caller
.
4. callAs is executed to call RepoDriver with calldata
5. RepoDriver using Context calls Drips
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 can see the point, why we can't make this contract the public entry point because we would have to verify some signatures.
Did you consider generalizing Caller
with a function that allows to extend calldata
with information from a DataStore?
Maybe also a bit complex
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.
One other idea could be to implement the signature verification part as a libary and you are using it here as well.
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.
We would basically allow the signature of the calldata
with the hash to be replaced with the actual calldata
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.
The data proxies are the public entry points. The user needs to approve
the data proxy address once, but after that they can call the data proxy directly, even in multiple separate transactions. The actual flow is:
- User calls Caller.approve(RepoDriverDataProxy)
(then)
- User calls RepoDriverDataProxy
- RepoDriverDataProxy is authorized to call Caller and calls Caller.
- callAs is executed to call RepoDriver with calldata
- RepoDriver using Context calls Drips
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.
Mhm, how would you prevent an attacker calling for another user's account after the approval?
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.
setStreams
would also allow to withdraw the funds. 🤔
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.
We would basically allow the signature of the
calldata
with the hash to be replaced with the actualcalldata
I was thinking about storing the entire calldata and not just the configuration lists, but it seems less useful. It's more opaque, so it's more difficult to analyze if it's a part of the proposal. At least the storage streams and splits hashes match the hashes used and emitted by Drips, which too helps with transparency. The Drips API relies a lot on sending the same data multiple times, e.g. you send you splits receivers when setting splits, and then on each splitting, it's similar with streams, you send them at least twice.
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.
Mhm, how would you prevent an attacker calling for another user's account after the approval?
In _callRepoDriver
helper we have this line: return caller.callAs(_msgSender(), address(repoDriver), data);
, which feeds the proper sender into Caller
. If the sender is an EOA, then Caller will try to act on behalf of that EOA. If the sender is Caller
, then the same sender will be looped back to Caller
.
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 see. Then it makes sense since only the _msgSender()
is passed
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.
It looks good in general but I have some questions about potential other designs since we have the callback to Caller
No description provided.