Creating a thread to track a potential footgun for cross contract calls with the new auth-next pattern.
Discussion from soroban-chat:
mootz12: Has anyone tested auth-next from the perspective of contracts much?
Curious if any1 knows the expected behavior of require_auth given the following situation:
ContractA calls ContractB, that contains a function doing the following:
fn contract_b_function(contractA: Address) {
contractA.require_auth(); // I expect this to pass
// .... some cool contract logic
let token_client = // some token client
token_client.xfer(contractA, env.current_contract_address(), 123);
// ^ would the `require_auth` call for contractA pass in the token contract?
}
[11:57 AM]tdep: I haven't tested it but I don't see why it wouldn't work (after all, it does work with stellar accounts). I think that the footprint (are contract auths generated upon simulation like for stellar accounts? thinking about this it would seem not as it's an intrinsic property of a contract to call certain functions, while it isn't for stellar accounts so they need to generate and sign the auth) comes into play here as it would tell to generate auth for both contract_b_function() and xfer().
[11:59 AM]tdep: ^^ but that's just an assumption
[12:07 PM]mootz12: (I think it works this way, but the WASM integration testing might not be fully accurate for this, cause I can submit transactions through any Address without generating signatures)
If feels like this is a requirement to work for consistencies sake. That being said, this is different than Ethereum in terms of an authentication pattern. msg.sender is only the previous invoker (IE require-auth for the token would fail in this example cause contractB is the "sender")
[12:08 PM]tdep: This would mean that a contract A that exposes a function like the following where for example the contract accepts another contract to invoke as argument without further checks:
fn ctr_f(e: Env, to_invoke: ByteN<32>) {
e.invoke_contract(&e, &to_invoke, (..., e.current_contract_address()).into());
}
would be exploitable by to_invoke since it could simply just pass the contract A address provided as param to a token contract (or even to whitelisted methods). Which is something that wouldn't work on ethereum with msg.sender
[12:10 PM]mootz12: Yeah, if this does work the calling contract would need to be incredibly careful about what they call, cause they are basically signing anything.