I am reading through UniswapV2 docs and can't understand the inputs of addLiquidity method properly.
As listed in the docs:
amountAMin (uint): Bounds the extent to which the B/A price can go up before the transaction reverts. Must be <= amountADesired.
amountBMin (uint): Bounds the extent to which the A/B price can go up before the transaction reverts. Must be <= amountBDesired.
What does it mean? Can you please give an example? Let's say, I set amountADesired and amountBDesired to 4 and amountAMin and amountBMin to 1. What will happen?
blockchain transactions are not immediate, but must queue before being mined on the blockchain and be effective
When you add liquidity given amountADesired you have to give it amountBDesired in proportion to the existing pair (example pair: 2:1 you have to put 2 tokens A and 1 token B)
once you send the transaction, before it is mined it may happen that others make operations on that liquidity pool, changing the proportion accordingly
by entering amountAmin and amountBmin you are practically telling him: "as long as the proportion is between amountADesired:amountBDesired and amountAMin:amountBmin accepts my liquidity addition, if instead the proportion exceeds my range, cancel my transaction"
Related
It seems transactions on polygon can get automatically dropped and replaced.
original: 0xa67609bacf51ab83b1989e4097b4147574b4e26399bec636c4cfc5e12dfa2897
replaced: 0xec0d501619b5fc9cde6af41df929eeded252138a49965f15a7598bf2e532e555
What is happening here?
On Ethereum, I believe this can only happy if someone proactively replaces the tx by submitting another with the same nonce and higher gas price. Is that correct?
{"level":"error","message":"Error: transaction was replaced [ See: https://links.ethers.org/v5-errors-TRANSACTION_REPLACED ] (cancelled=true, reason=\"replaced\", replacement={\"hash\":\"0xec0d501619b5fc9cde6af41df929eeded252138a49965f15a7598bf2e532e555\",\"type\":2,\"accessList\":[],\"blockHash\":\"0x252f663dfb64dd82dff77b5e4fbe2073cd77248c5ce8dff1191c87ac22d97cf9\",\"blockNumber\":39285028,\"transactionIndex\":60,\"confirmations\":2,\"from\":\"0x90Be1Ef5EEa48f1d33e2574a73E50D208bB3680E\",\"gasPrice\":{\"type\":\"BigNumber\",\"hex\":\"0x6cdbaaf8e5\"},\"maxPriorityFeePerGas\":{\"type\":\"BigNumber\",\"hex\":\"0x6cdbaaf8e5\"},\"maxFeePerGas\":{\"type\":\"BigNumber\",\"hex\":\"0x6cdbaaf8e5\"},\"gasLimit\":{\"type\":\"BigNumber\",\"hex\":\"0x0186a0\"},\"to\":\"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\",\"value\":{\"type\":\"BigNumber\",\"hex\":\"0x00\"},\"nonce\":112,\"data\":\"0xe3ee160e00000000000000000000000090be1ef5eea48f1d33e2574a73e50d208bb3680e00000000000000000000000090be1ef5eea48f1d33e2574a73e50d208bb3680e00000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000063eb95950000000000000000000000000000000000000000000000000000000063eb9b71c726f5f957d29df36c915d2f2816a5906bdb096a68d79abeb83102359a3c51ef000000000000000000000000000000000000000000000000000000000000001cbaca5b2bb8c9b3a25ba94b3303be256a72cc37172886b67140c788f53eacfa0526f4bc5dd18d1e0154a0c574c12ff67b656846a731cc55e32b7d60a8ae5b21ee\",\"r\":\"0x2503d5645a7620c94678ef0a5de4bca4e03b18943cec0511d58b7e444412b467\",\"s\":\"0x72c2cf739e2bfeb8335faab2c4b87b7b0464c9681a488456fa7c8fe25aef89c6\",\"v\":1,\"creates\":null,\"chainId\":137}, hash=\"0xa67609bacf51ab83b1989e4097b4147574b4e26399bec636c4cfc5e12dfa2897\", receipt={\"to\":\"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\",\"from\":\"0x90Be1Ef5EEa48f1d33e2574a73E50D208bB3680E\",\"contractAddress\":null,\"transactionIndex\":60,\"gasUsed\":{\"type\":\"BigNumber\",\"hex\":\"0x0110bc\"},\"logsBloom\":\"0x00000000000000001000000000000000000000000000000000000000000000000000000000000000020000000000000000008000000000000000000200000000000000000000000000000008000000800000000000000000000100000000000000000000000000000000000000000000020000000000000180000010000000000001000000400000000000008000000000008000000000004000000000000000200000000000000000000000000000000004000000000000000000000000004000100002000000000081000000000000000000000000000000100000000000000000008000000000800000000000000000000000000000000000000000100000\",\"blockHash\":\"0x252f663dfb64dd82dff77b5e4fbe2073cd77248c5ce8dff1191c87ac22d97cf9\",\"transactionHash\":\"0xec0d501619b5fc9cde6af41df929eeded252138a49965f15a7598bf2e532e555\",\"logs\":[{\"transactionIndex\":60,\"blockNumber\":39285028,\"transactionHash\":\"0xec0d501619b5fc9cde6af41df929eeded252138a49965f15a7598bf2e532e555\",\"address\":\"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\",\"topics\":[\"0x98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a5\",\"0x00000000000000000000000090be1ef5eea48f1d33e2574a73e50d208bb3680e\",\"0xc726f5f957d29df36c915d2f2816a5906bdb096a68d79abeb83102359a3c51ef\"],\"data\":\"0x\",\"logIndex\":250,\"blockHash\":\"0x252f663dfb64dd82dff77b5e4fbe2073cd77248c5ce8dff1191c87ac22d97cf9\"},{\"transactionIndex\":60,\"blockNumber\":39285028,\"transactionHash\":\"0xec0d501619b5fc9cde6af41df929eeded252138a49965f15a7598bf2e532e555\",\"address\":\"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\"0x00000000000000000000000090be1ef5eea48f1d33e2574a73e50d208bb3680e\",\"0x00000000000000000000000090be1ef5eea48f1d33e2574a73e50d208bb3680e\"],\"data\":\"0x0000000000000000000000000000000000000000000000000000000000002710\",\"logIndex\":251,\"blockHash\":\"0x252f663dfb64dd82dff77b5e4fbe2073cd77248c5ce8dff1191c87ac22d97cf9\"},{\"transactionIndex\":60,\"blockNumber\":39285028,\"transactionHash\":\"0xec0d501619b5fc9cde6af41df929eeded252138a49965f15a7598bf2e532e555\",\"address\":\"0x0000000000000000000000000000000000001010\",\"topics\":[\"0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63\",\"0x0000000000000000000000000000000000000000000000000000000000001010\",\"0x00000000000000000000000090be1ef5eea48f1d33e2574a73e50d208bb3680e\",\"0x000000000000000000000000e7e2cb8c81c10ff191a73fe266788c9ce62ec754\"],\"data\":\"0x00000000000000000000000000000000000000000000000000080d77c3b67cb80000000000000000000000000000000000000000000000003005ebfb86a0d1350000000000000000000000000000000000000000000003ebfb8e3e34e504eca50000000000000000000000000000000000000000000000002ffdde83c2ea547d0000000000000000000000000000000000000000000003ebfb964baca8bb695d\",\"logIndex\":252,\"blockHash\":\"0x252f663dfb64dd82dff77b5e4fbe2073cd77248c5ce8dff1191c87ac22d97cf9\"}],\"blockNumber\":39285028,\"confirmations\":2,\"cumulativeGasUsed\":{\"type\":\"BigNumber\",\"hex\":\"0x8d88d1\"},\"effectiveGasPrice\":{\"type\":\"BigNumber\",\"hex\":\"0x6cdbaaf8e5\"},\"status\":1,\"type\":2,\"byzantium\":true}, code=TRANSACTION_REPLACED, version=providers/5.7.1)"}
On Ethereum, I believe this can only happy if someone proactively replaces the tx by submitting another with the same nonce and higher gas price. Is that correct?
Yes, and the same is possible on Polygon and other EVM chains.
Senders can replace their transactions for multiple reasons. For example, high-frequency trading bots continuously check if their pending transactions are still likely to be profitable - and if the transaction is not going to be profitable, the bot replaces it with another one. Either with new recalculated params that they expect to be profitable or simply with transaction from/to the same address so at least they don't lose any more funds than just the gas fees.
Note: Once you send a transaction, it's impossible to drop it completely from the mempool. That's why it is sent back to the sender address.
Or sometimes transactions are replaced by regular users that specified insufficient gasPrice and want to speed up the transaction by replacing the gas price with a higher value.
I am asking this question so that I want to easily know how many transactions occurred at a particular Bitcoin price. For example, at the price of $20T per BTC, how many are they?
There could be other ways finding this correlation, but my question is: Does the block stores this dollar value?
It does not.
Each block contains a list of transactions and other metadata such as block number, timestamp when it was mined, etc... But the fiat monetary value is not part of the block, nor a part of a transaction.
You'll also need to define a source of truth for the price. While a specific block was mined on a specific time, the price of Bitcoin at that specific time was slightly different on each exchange.
Example (values are made up):
Block number 500,000 was mined on 2022-01-01 00:00:00.
At this exact time, the highest bid on Binance was $19,990, the lowest ask on Binance was $20,000, the highest bid on Coinbase was $20,050, the lowest ask on Coinbase was $20,070, etc.
Exchanges and aggregation services (such as Coinmarketcap) often offer some average prices through their API for a specified timeframe. But there's no "one price of Bitcoin at a specified time".
Don't kill me if I'm about to ask something stupid. But I'm very noobish in this whole crypto world, and I'm terribly fascinated about its technology.
So just for education purposes I've decided to build my own blockchain following more or less the bitcoin principles (ECC keypair generation using the secpbk1 curve, SHA256 as hashing algo, dynamic diff based on the timestamp of the previous block, p2p connectivity etc..). But I've came to a point where I'm pretty confused about the blockchain's wallet itself.
For what I've learned so far, each transaction has to be signed by a wallet. So my transactions has basically three fields: input, outputs and id. Since the user's wallet signs the outputs field of the transaction, this can't be changed anymore without being signed again by the same private key that belongs to the public key contained in the input field, how can I reward the miners?
If I got it right, the miner creates a transaction signed somehow by the chain using the fee in the outputs field, or by asking the chain itself to generate and sign a special reward transaction for that miner.
The guide that I was following was using the second approach, and was generating a blockchain wallet each time the program was executed on a client. This approach left me perplexed:
wouldn't a client generate a new wallet for "his" blockchain each time it goes back online? If so, wouldn't this create a mess on the transactions signed on the chain? Since each miner (therefore peer) signing its own reward would use a different blockchain wallet than the other peers? Wouldn't this lead to any problems?
The first one that I might think of, is that if we generate a new blockchain wallet that signs rewards for miners, each peer would create a different wallet, so wouldn't this lead to many "ghosts" wallets in the chain, that spits out rewards tokens from nowhere? Is this supposed to happen?
For what I think is definitively more straightforward to use the fee amount to reward the miner, but this doesn't solve my doubts at all. Since the outputs of the transactions are signed upon creation, how could the peer initiating the transaction know upfront the possible miner who finds the block? And if he can't know it, how could possibly the miner "extract" its reward without tampering the transaction itself? Of course it could create a new transaction, and add that to the block. But who would sign that transaction? From where those reward tokens come?
And if the answer is not to generate a new wallet each time, where could you possibly store that very first private key of the chain's wallet where no one can see it, but still be able to use it, without having to put a server in the middle?
Which in my opinion breaks the whole decentralized concept and would add a single point of failure.
I've also implemented a transactions pool, that automatically filters out invalid (tampered) transactions, whenever a miner requests a sub set of them to stamp in a block. But does this mean that the miner for that only exception can tamper the transaction since it'll be "forged" in the block? So who gives a *** if it was tampered once it got in the chain? MEEEEEH that doesn't sound nice at all.
I'm terribly confused, and I'm dreaming key pairs at night. Please help me.
wouldn't a client generate a new wallet for "his" blockchain each time it goes back online? If so, wouldn't this create a mess on the transactions signed on the chain? Since each miner (therefore peer) signing its own reward would use a different blockchain wallet than the other peers? Wouldn't this lead to any problems?
You don't say what problems you think this will lead to. I can't think of any.
For what I think is definitively more straightforward to use the fee amount to reward the miner, but this doesn't solve my doubts at all. Since the outputs of the transactions are signed upon creation, how could the peer initiating the transaction know upfront the possible miner who finds the block? And if he can't know it, how could possibly the miner "extract" its reward without tampering the transaction itself?
The simplest solution to this is for the transaction itself to just contain its inputs and outputs. The fee is the difference between the total inputs and the total outputs.
The miner just includes the transaction in the block of transactions they mine. They also add one additional transaction into the block, sending themselves the reward. Obviously, they know their own destination address. Every participant who receives the newly-mined block checks to make sure this transaction is valid (just as they check every other one) and doesn't claim a larger reward than is allowed.
And if the answer is not to generate a new wallet each time, where could you possibly store that very first private key of the chain's wallet where no one can see it, but still be able to use it, without having to put a server in the middle?
Typically in a file on the local disk. The private key isn't really needed anyway -- you only need it to send. You don't need it to mine or report. So it can be prompted for or decrypted only when actually needed.
Of course it could create a new transaction, and add that to the block. But who would sign that transaction? From where those reward tokens come?
The usual rule is that the reward transaction has no inputs, one output, and no signature. The tokens come from the pool of unclaimed miner reward tokens which can be finite or infinite depending on the blockchain's design. (For bitcoin, this pool is finite.)
How does one program a Cryptocurrency Miner?
Like
XMRig
XMR-Stak
MinerGate
etc.
You would first need to have a understanding of the concept of PoW. Simply put PoW is hashcash - a miner hashes the block they have created, incrementing a random "nonce" (number used once) until the resultant hash fulfills the "difficulty" requirements. The difficulty is a number that is calculated based on the time between the blocks over the last 2 weeks, it changes to keep blocks being made every 10 mins (ish). For a block to be accepted its hash must be under the difficulty value (and the block must be valid of course). Solo mining software works by polling the coins daemon for the block template (this contains all the highest fee transactions in some cases, in others you have to add them yourself) creating a "coinbase" transaction (a transaction which will pay you the reward once you find a valid block, this is appended to the top of the list of transactions) updating the merkle root of the transactions to include the new coinbase transaction and adding a nonce, you then hash this block - check if the hash fulfills the difficulty and if it doesn't then increment the nonce. The miner keeps doing this until:
1) The miner finds a block - in which case it sends the block to the daemon
2) A block is found by someone else, in which case the miner starts again (getting the new block template bla bla bla).
However most miners are pool miners - in this case the miner connects to a pool via the stratum+tcp protocol and requests a "job", a job is just a string the pool wants you to hash - the pool does the jb of creating the block to be hashed then splits up the task of hashing over all the miners connected. For example the pool might tell alice to hash the block with nonce 0 up to nonce 15,000 and bob to hash with nonce from 15,001 to 30,000, and so on. The pool miner then submits the result of the work. Once a miner finds a solution they tell the pool and the pool sends the block to the pools daemon, it tells the other miners to stop and start work on the new block. It then splits the reward to the miners based on how many jobs they completed - though the way in which this is done is out of the scope of this answer).
TLDR;
You need to have a understanding of how PoW works, a understanding of what method you want to mine with (solo or pool), (if pool) you'll need to understand the tcp+stratum protocol and (if solo) you will need to understand the rpc of the coin you want to make a miner for. I would start by reading through basic and simple solominers, and then building one of your own. Then you can consider moving onto pool miners which are considerably more complicated. If you want your miner to work with GPUs (and most miners do) then you will need to understand common GPU interfaces for both NVIDIA (eg CUDA) and AMD.
I hope this helps and the best of luck and wishes regarding your adventure into the cryptoverse!
Leo Cornelius
I have two identical transactions, in this case sending same amount of tokens, that result in different actual gas consumed (NOT the cost, and a significant difference).
Here are the tx hashes:
0x2cbb4b35d87cabe1a7b7bcb562e4e046e9ef0b4b27ac9de99a6a3ebf6d088f89
0x9b1d32a07d0332b55b800c59f860acef8791a7da6be5105ff2d2ed579fecb334
At first I thought the data might cause the difference (amount of '0' in the payload?) or the difference in mining difficulty for their corresponding blocks, but none of these seem to justify this Gas use gap (if relevant at all)
Does anyone have an explanation of how come this happens?
Note that I have more transactions like these that present the same gaps.
Tnx!
UPDATE
Following smarx comment below - it sounds right, however, I would expect to have 4 different Gas values at most (2X2 combinations, as you have mentioned). In reality, we have more than 4 different results. Here are few transactions, with their Gas usage values:
22280 0x26c4b28a068e6ec91579c96e32aba449f2ad73168aca51e476a5a84072a620b6
22344 0x1341a9c4f6641746a50f8d05bb907d16150edf5e313b697908ddf3546e8fb9ae
22408 0x163eed32fee0f5999505dff804bd047620d0c063e07ad142ba0e257ed30cc4ee
22472 0xec326e42069efdefc79bd07fa98724ca2ec00432129cc3179e582a0e88af5112
22536 0xbd06b1722447fa8aaa783717c8237dd8b3934137ac8eabfd20bbdc6d1ec1af50
22600 0x9c3df4902887c94f9bf7901b8273c8b9da94d36f80801c3c5dbec9b4e7a5d8a8
36960 0x0ec051a92b1821d264f70b949cae68c2f463ae741330dc6a3a103b2612d1ea1c
37280 0x233e7c7abbf0e482c4c5b55efb31a7cd3c073ab00d2116fcff171f9e71542c1b
37344 0x3a93f860418732e76ca5941d7f9e6f0ec78df19905b8303ea520cea0994168aa
37408 0x6ce02124e33088fa7d13bfe2802039afecd78ba10e0a46598dea577c2ea61f27
37472 0x1f5be1f26f97f74aeb06d156d2221854597673640bc3c38690191501d2cd8f71
37536 0xd0edcfe4c179294bffca80f812a4a827a560294a1d944ac77adb9b8a0b22aa60
37600 0x2d7eca881486d69968eb3ab1f16850c0cd497003d06a2ea61efaeed6467f9a6a
52280 0x77d607600bf0110785cd08de78399d61c369274baa3a180841bc0d1f015f328d
52344 0xa0a3f46e35abe608c27cec2cc188beddabad724ea6362a4584e9325a5cd9d276
52408 0x41c63e00b4e58ce2292a17216e7dc2554733feb70d2a0fe9c505689ef1dd50a3
52472 0x4ed5e9366948a23340b7f572dc69da5b0525cc4f7b5d0ddd83945ef4cdbaf05c
52536 0x40b33b7f9bc08171b1b2f54241db6f58ae72bd89c9b9d7650ba3ca5174144dcd
Just a guess, but a fairly likely one:
The transfer function does two writes to storage:
Update the balance of the from address.
Update the balance of the to address.
Writing to storage has different gas costs depending on the previous value and the new value.
My guess is that in the first transaction, the to address has an initial balance of zero, and the from address still has some tokens left after the transaction. Changing a zero in storage to a non-zero value costs 20,000 gas, so this is the cost of updating the to address. Changing a non-zero value to another non-zero value has a gas cost of 5,000 gas, so that's the cost for updating the from address. Total cost of the two store instructions: 25,000.
My guess is that in the second transaction, the to address has a positive initial balance that is increased, and the balance of the from address is fully depleted by the transaction. Updating the to address costs 5,000 gas (changing a non-zero value to another non-zero value). Updating the from address involves changing a non-zero value to a zero, for which you get a gas refund. The cost is 5,000 gas but then a gas refund of 15,000 is given at the end of the transaction. That's a net cost of -10,000, so the total for the two store instructions is -5,000.
The difference between 25,000 and -5,000 is 30,000, which is precisely the gas difference between the two transactions.