#Is there any way to get the address of the account/contract invoking the contract?
12 messages · Page 1 of 1 (latest)
I think I get this one, correct me if I'm wrong. Before we were technically borrowing the auth from the transaction signature basically saying give me whoever signed this transaction and let's just hope/assume they're fine with whatever we're about to do with their account inside this contract. Now via auth next you can very cleanly separate the signer of the transaction to submit the smart contract call from the allowed permissions inside the smart contract function call. Pretty smart.
However requiring there be no method whatsoever to even get the address, authorized or not of the invoker seems too harsh. Seems like it'll end up resulting in a lot of arg repetition/duplication where you're just always passing in the contract signer Address as an arg. I like the option, not sure how I feel about the requirement. What if you could have an env.invoker and could choose to call env.invoker.require_auth() if you wanted to?
The problem with providing direct access to invoker is that people might indeed use it for authorization and bypass account abstraction. In fact, if they come from other ecosystems with msg.sender like functionality that might appear to be the "right" way to do authorization.
In addition, maybe this is personal preference but I do feel like having the account being authorized as an explicit function argument makes code more readable.
Consider the ERC20 transfer function:
function transfer(address to, uint256 value) public returns (bool success)
Isn't it a bit uncanny that there's no from argument there?
i often used invoker in the same way as msg.sender you're right
yeah, removing the invoker is a conscious decision to avoid auth approach fragmentation which we had before and which we wanted to consolidate in Auth Next. transaction invoker shoudn't have any special meaning anymore
I do see, however, how it might be useful to know about the contract invoker (e.g. to check that your contract is always invoked from some specific contract or is never invoked from another contract etc.). but that can be achieved via a get_call_stack host fn, that is more comprehensive on one hand, but isn't trivially compatible with auth to avoid the footguns
also, while we do add additional args in some cases, we can get rid of them in the other. E.g. for the token admin ops we don't need to pass the admin address in the invocation and do additional authorization (we do know, but that's planned to be changed in the next release). so you can do just env.storage().get(&DataKey::Admin).require_auth(), which both saves an argument and also gets rid of an additional unnecessary authorization check we do now (if invoker == admin)
Thanks for this additional info
thanks for the env.storage().get(&DataKey::Admin).require_auth() example, hadn't thought about that method
This context is helpful
Still think env.invoker.require_auth() would be a nice-to-have feature
it would be kind of meaningless... invoker has already signed the transaction, so it's not clear what would that even mean
what could be provided is to special-case one address and put it into env (like env.authorized_invoker() or something). but I feel like this may introduce more fragmentation into contract API styles (like if I look at do_stuff(a: Address, b: int128), how do I know that it also uses authorized_invoker?) that applies to some degree to the current APIs too (as you can get the address from the storage), but that's just one more degree of inconsistency...