#How can I protect read-only functions?

9 messages · Page 1 of 1 (latest)

whole quartz
#

I write a smart contract that has a read-only function.

I am aware a contract should not store sensible info. However, I want to ensure that this function is only called by the contract owner (the same address that initialized the contract) since the data returned by this function is let's call it "private" to the owner and only the owner should have access to this.

To achieve this, in the function I validate that the address sent as an argument is equals to the contract owner, and then do address.require_auth(). This works.

    /// Gets the super secret data stored in the contract. Only the owner can call this function.
    pub fn get_data(env: Env, address: Address) -> Data {
        authentication::check_admin_address(&env, &address);
        address.require_auth();
        storage::get_data(&env)
    }

But I just realized that the simulateTransaction returns the value anyway, ignoring this address.require_auth step. Is this okay? 🤔

So what is the way to ensure that a read-only function only returns data if it is invoked by the contract owner?

scenic bone
#

Simulation allows calling any function bypassing auth. During simulation the function isn't running on the network, it's running on the soroban-rpc locally.

#

On the network the auth will only succeed if authorized.

round oriole
#

tip of the day: you can use env.storage().get(DataKey::Admin).require_auth() and skip passing an explicit address

whole quartz
#

@scenic bone thank you for replying

Taking into account that the function is read-only then it does not matter to have that require_auth, right?

I can get the data without submitting any tx but just simulating

whole quartz
round oriole
#

data on ledger is public by definition, so you obviously can't prevent it from being read off-chain (unless you encrypt it, that is). however, if someone wants to use this function on-chain, they'd need to authorize it

#

I'm not sure about your particular use case, but one can imagine some oracle contract that only provides data to a certain set of authorized users (e.g. those who have payed some fee). this way function will still be RO, but only authorized users will be able to use it on-chain

#

(FWIW I don't know if that's a viable/good idea, but it's definitely possible to implement)