NEAR protocol is sharded and transactions between cross-contract calls in shards are final. In some cases, it would make sense to identify longer transaction chains, especially if the promise chain hits the same contract twice (re-entrancy).
Let's imagine a chain of promises: Alice wants to buy a token and the trade is routed through multiple smart contracts and hits one contract in the chain twice.
Alice (user) (tx 1) ->
exchange contract (triggers promise 1) ->
aggregator contract (triggers promise 2) ->
pool contact (triggers promise 3) ->
exchange contract (again)
The exchange contract can identify Alice's account with signer_account_id. However can the exchange contract know about the re-entrancy, namely tx 1 or promise 1, and is it possible to resolve or infer this from the smart contract execution context, so that the exchange would know it is already processing trade for Alice?
Note that Alice may have two chain of promises being processed at the same time, so signer_account_id is not enough uniquely to identify the chain of promises.
I am looking in VMContext and trying to figure out how this is possible.
In the contract environment, you have to pass all the necessary information through arguments.
Off-chain you can use NEAR Indexer or JSONRPC EXPERIMENTAL_tx_status method to get all the receipts and their outcomes
Related
It seems wNEAR is baked by wrap.near contract, but how does it work?
wrap.near holds w-near contract, which is FT [fungible token] implementation based on NEP-141 standard.
The idea is simple, you send native NEAR tokens and the contract keeps track of the balance of the sender account in its local storage, and there is a reverse operation which allows you to instruct the contract to send NEAR tokens back.
This FT always matches native NEAR token 1:1. "Wrapped" prefix in the name (wrapped NEAR or wNEAR) implies that it just turns native token into FT token. It was created to be compatible with Rainbow Bridge (Aurora) interfaces which allows to transfer FT across NEAR network <> Ethereum network (by locking the tokens in a contract on one network and unlocking the equivalent amount of tokens from a contract that is deployed on the other network).
So getting back to the technical implementation of w-near contract, you can find three core methods:
near_deposit expects NEAR native tokens attached to the function call, and those attached tokens will be deposited to wrap.near account, and in exchange the contract implementation will save a record in the storage that those tokens belong to the account that sent them
near_withdraw deducts the amount of tokens recorded for the account that called this function and sends a transfer of native NEAR tokens back to the caller
ft_transfer (it is implemented by near-sdk-rs helper) virtually transfers the wNEAR FT tokens by updating the records inside the contract storage. NOTE: there is no native transfer involved here, so the transaction will go from tokens sender to wrap.near contract, which will update the balances of the sender and receiver accordingly, and the receiver account will never receive a native NEAR call or NEAR tokens (until he/she calls near_withdraw)
I want to know if there's a concept similar to Meta-transactions in Substrate.
"A meta transaction is a regular Ethereum transaction which contains another transaction, the actual transaction. The actual transaction is signed by a user and then sent to an operator or something similar, no gas and blockchain interaction required. The operator takes this signed transaction and submits it to the blockchain paying for the fees himself." 2
You can learn further about meta-transactions in Ethereum from these articles:
Ethereum Meta-Transactions 101
How to implement generalized Meta-transactions?
I want to implement a substrate pallet where I can airdrop certain amount of tokens native to the substrate blockchain and let users with 0 balance claim according to their interaction with some other protocols built on other blockchains.
I researched some feeless mechanisms in Substrate and built a feeless pallet inspired from tutorials by Shawn tabrizi so that my pallet could send balance to users for a certain transaction. But I don't see how I can best implement this mechanism without risking a sybil attack on the blockchain. In ethereum, due to the concept of meta-transactions, it's pretty easy to onboard new users to a certain protocol. What's a possible equivalent case in Substrate for onboarding non-substrate users to a new substrate blockchain?
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).
I am writing a set of interacting smart contracts for a NEAR blockchain. Let's imagine the the following scenario
User sends a token to an exchange smart contract
Token smart contract calls exchange smart contract
Exchange smart contract calls fee smart contract
Exchange smart contract calls another token contract to send back another set token in the trade
Unlike a single shard Ethereum, NEAR does cross contract calls with promises. Whereas a single tripped require() automatically rolls back to the whole Ethereum transactions, in the sharded nature to NEAR smart contracts themselves are responsible for rolling back state changes if the promise they triggered does not complete successfully.
My question is how to safely handle failures in the chain of promises between NEAR smart contracts
What are the failure modes (smart contract function panics, target account does not contain code, out of gas)
How to catch the different errors above and deal with different error modes
Is there already a pattern that allows writing promise chains safely in an easy manner, similar to try {} catch {} in JavaScript await/async model
How I can track between different promises what was the original initiating user transaction that caused the chain of promises to trigger
How smart contracts are forwarding gas and ensuring there is enough gas for the whole chain of promises to complete
Generally you can only tell whether a promise has succeeded without knowing what goes wrong in the case of an error. An example of such a check can be found here https://github.com/near/core-contracts/blob/4f245101d7d029ffb3450c560770db244fc7b3ce/lockup/src/utils.rs#L7. What is the use case of reacting differently to different error that you have in mind?
In today's Substrate Collaborative Learning, the SignedExtension impl for CheckGenesis came up (see this riot conversation for validation-related discussion).
Going back to first principles, what are the use case(s) for CheckGenesis ?
When a user submits a transaction to a Substrate-based blockchain, there is extra signed data attached to the transaction to ensure it is applied to the correct chain state that the user intended it for. You can see what kind of additional signed data is attached in the node template
The purpose of CheckGenesis is to ensure that the transaction is submitted to the correct chain instead of a different one. Without CheckGenesis, the following attack would be possible.
Alice pays Bob a few tokens on a chain that they both commonly use.
The transaction goes through as expected and Bob receives the tokens.
Bob notices that Alice re-uses her key on another chain.
So he submits her transaction to that second chain as well.
The transaction also goes through on the second chain, and Bob receives a second payment.
By referring to the chain that the transaction is intended for in the signed data, Alice can prevent that attack.
As cryptographic advice, you should not reuse keys across applications in general. Not all blockchains are based on Substrate, and not all chains include this check.