Is it safe to share a NEAR protocol function access key publicly if only limited to intended functions? - nearprotocol

Given I want to let someone without a NEAR account call a specific function in a smart contract, and to do so I create a function access key for my own account with permissions limited to that specific contract and function.
Will I then risk anything else than the allowance (0.25N) granted to that function access key?
Is it a bad idea to even share that access key publicly, let's say if I want to include that access key in a link?
I could of course also create an implicit account and then a function access key from that, but is it really necessary from a security point of view?

What you're describing is the basis for what's known as a linkdrop. You can learn more about how those work here.
To answer your question, it depends on what that function call access key can do. If it can call a method withdraw that can withdraw $NEAR from your contract account with no limits, then it's probably not a good idea to share it publicly.
If you're confident that the key cannot be used in a malicious way to steal assets or do things that are unwanted, then there is no risk in sharing it publicly.
I would also stress that the 0.25 $NEAR allowance is NOT saying "this key can be used to withdraw up to 0.25 $NEAR on my account". That allowance is for transactions fees ONLY (Gas). 0.25 $NEAR equates to roughly 2.5 PetaGas (2500 TGas) which is a lot of computation power and can be used to call a method many times. What happens in that method, however, has nothing to do with the allowance.
You can spend 0.01 $NEAR worth of allowance (100 TGas) and call a method which withdraws 1000 $NEAR from the contract account. The allowance is ONLY for computation.
TLDR: it depends on what the key can do and allowance != net outbound NEAR from a contract account.

Related

How to calculate storage rent?

I send transactions programmatically and I need to know exactly how much the fee is going to be. I managed to figure out how to calculate fees for ordinary transaction ((transfer cost + receipt creation cost) * 2), but now I'm struggling with a case where I need all my funds out of the account without deleting it. As I understand, in this case there must be a storage rent left on the account. However, I can't really figure out how to calculate that rent. There is a value returned from 'EXPERIMENTAL_protocol_config' method that seem to be connected to rent - 'storage_amount_per_byte', which implies that each byte costs 10000000000000000000 yocto, and also I can get 'storage_usage' from 'query' method with request type 'view_account', which is supposedly indicated how many bytes my account uses (which is 182). But whenever I try to send a transaction, I get a 'NotEnoughBalance' error that states that transaction cost is higher than the balance, but just by 669547687500000000 yocto. Whatever I do, I can't understand where this number comes from. No combination of fees from aforementioned 'EXPERIMENTAL_protocol_config' method yields this number.
There seems to be little to no decent documentation on transaction fee calculation, except for some 'fixed' values for most used actions. If you have any info on fee/storage rent calculation - I'll be thankful for it.
Through a random chance, I managed to find out the name that the number '6695476875' is referred to as, 'Reserved for transactions', (in gas, not tokens) as in the official wallet (wallet.near.org). God knows why it is reserved, neither docs.near.org, nomicon.io nor wiki.near.org have any info regarding this 'reservation' and this number is never mentioned in any RPC API method. This number is also never mentioned in 'near-api-js' lib, so I really have no idea if devs are even aware of it.
Anyway, since the title of this problem is 'How to calculate storage rent', the answer is something like this:
You get account info from 'query' method of RPC API (here's the doc) and take the "storage_usage" value (this is the amount of bytes that your account takes up on the blockchain).
You get protocol info from 'EXPERIMENTAL_protocol_config' method of RPC API (here's the doc) and take the "storage_amount_per_byte" value.
You multiply the amount of bytes by the storage_amount_per_byte and add the magic 669547687500000000 number to it.
And the resulting number is the least amount of tokens that you must have at your account at any time.
I don't know why it is a common practice to make lives of developers harder in blockchain industry, but this is a good example of such practice.

Why the transferable to smart contract is deducted?

I uploaded and created a new smart contract. I sent 1000 units to this smart contract.
However when the contract is deployed the transferable is not equal to 1000.
And when I execute any function it also deducts the transferable.
Is there any way to prevent this. I want to deduct user token instead of the smart contract token. In Ethereum, the user token is deducted.
I want to deduct user token instead of the smart contract token. In Ethereum, the user token is deducted.
I think there is a misunderstanding here, you probably understood the deducted tokens as gas. But gas is deducted from the instantiating account (what you referred to as "user token"), same as in Ethereum.
The amount that is deducted from the contract here is state rent ‒ i.e. the contract has to regularly pay for the amount of state and code storage it uses. This is a concept which is currently used by the contracts pallet to reduce state bloat. I won't link to the documentation here though, since a new paradigm will be introduced soon, making it obsolete.

Why does it require tokens to set up an account on NEAR?

To set up an account on the NEAR blockchain, it requires you to send some number of tokens to fund that account. For example, when using the NEAR Wallet to set up a new account, you have to fund it with 3N first. Why is this?
You can create a NEAR "implicit" account with 0 NEAR. Near implicit accounts are the same as in Ethereum or Bitcoin. You create the a keypair locally and the public key becomes your account id (a hex string, like in Ethereum or Bitcoin)
See here: https://nomicon.io/DataStructures/Account.html
and here: https://docs.near.org/docs/roles/integrator/implicit-accounts
You only need 3 NEAR if you want to create a "named" account, that is an account like alice.near that's way easier to use than implicit accounts like 641537c21dC82F97b7fC8AD778e99997beeE0d73
On NEAR, data usage is "funded" by holding a balance of tokens on the account which reserves the storage space. So, in order for the account to be created, it has to set aside some storage on the chain, which requires some amount of tokens to "pay" for those initial bytes of memory by sitting on the account.
This minimum balance depends on how much data the account uses and could start as low as < 1N for a basic account to ~40N for one with multifactor authentication and other bells and whistles added to it.
For more, see the docs at https://docs.near.org/docs/concepts/storage which describe the "state staking" approach used here.

How to view data in NEAR protocol contract for free?

Should I pay for every read from NEAR protocol?
How do I view the value stored in NEAR protocol smart contract? (e.g. staking pool fees)
What is the difference between view and change methods?
Should I pay for every read from NEAR protocol?
TL;DR: No, you should not.
In NEAR protocol there are to ways to interact with smart contracts:
Submit a transaction with a FunctionCall action, which will get the specified method executed on the chunk producing nodes and the result will be provable through the blockchain (in terms of near-api-js these are "change methods")
Call query(call_function) JSON RPC method, which will get the specified method executed on the RPC node itself in a read-only environment, and the call will never be recorded/proved through the blockchain (in terms of near-api-js these are "view methods")
You can change the state and chained operations (e.g. cross-contract calls, tokens transfer, or access key addition/deletion) only through the first approach since blockchain expects the user to cover the execution costs, so the user should sign their transaction, and they will get charged for the execution.
Sometimes, you don't need to change the state, instead, you only want to read a value stored on the chain, and paying for it is suboptimal (though if you need to prove that the operation has been made it might still be desirable). In this case, you would prefer the second approach. Calling a method through JSON RPC is free of charge and provides a limited context during the contract execution, but it is enough in some scenarios (e.g. when you want to check what is the staking pool fee, or who is the owner of the contract, etc).

How to attach value (deposit) to transaction with Nearlib?

Let's say I have a contract function that expects a certain amount of near to be send with a certain transaction, the function is called create_order, create_order takes a couple arguments.
I have my contract setup in the frontend under the name myContract.
I want to call myContract.create_order({...}) but the transaction fails because this method call doesn't have the right amount of NEAR tokens attached.
How do I assign a certain value of deposit to a transaction?
It's possible to use account.functionCall directly (without sugar for RPCs) to either attach amount or specify gas allowance for the call.
See Account#functionCall in nearlib.
Nearlib supports it using account.functionCall(..., amount). But it might not work, because of the design of the access keys with function calls. Default authorized access keys towards applications only allows function calls without attached token deposits (only prepaid gas). It's done this way to prevent apps from automatically using your balance without your explicit approval. Details on access keys are here: https://github.com/nearprotocol/NEPs/blob/master/text/0005-access-keys.md
The way to attach a deposit for the transaction should be done with the explicit approval from the wallet. The app should create a request for the wallet, redirect to the wallet for the approval (or through the popup). Once user approves the transaction, it's signed with full access key from the wallet directly and broadcasted. But I'm afraid we don't have this API on the wallet yet. Issue for this: https://github.com/nearprotocol/near-wallet/issues/56
AFAIK it is not supported at the moment. It will be available after this NEP https://github.com/nearprotocol/NEPs/pull/13 lands.

Resources