I want to perform an atomic token swap without a pre-deployed smart-contract and I am wondering how to do that in Solidity.
The most common approach to do atomic swaps between tokenA and tokenB is the P2-SC-2P (Peer-to-Smart-contract-to-Peer) approach:
deploy a token swap smart-contract
alice deposits tokenA in the smart-contract
bob deposits tokenB in the smart-contract and receives tokenA in exchange
I want to get rid of step 1 to have a truly P2P mechanism. The main idea would be that Alice signs a transactions that transfers X tokenA to the person propagating the transaction, only if that person transfers Y tokenB to Alice in return.
Is it even possible to implement something like this?
Technically speaking, my first thought was to have Alice sign a transaction that deploys a smart-contract would take care of making the atomic swap between the signer and the caller before self-destructing.
I am not a good Solidity dev (to say the least) so here is the pseudo Solidity code I had in mind that could perform the atomic swap without requiring a pre-deployed smart-contract:
contract AtomicSwap {
sellerSignedApprovalTx = "<RawSignedTxData>"
constructor() public {
buyer = caller
seller = verifySignature(sellerSignedApprovalTx)
TokenB.approve(buyer,sellerSignedApprovalTx.askPrice)
delegateCall(sellerSignedApprovalTx.data)
safeTransferFrom(TokenB,buyer,seller,sellerSignerApprovalTx.askPrice)
safeTransferFrom(TokenA,seller,buyer,sellerSignerApprovalTx.tokenAmount)
selfdestruct()
}
}
As you can see, the idea is that the smart-contract has only 1 use: it performs the swap and then self-destructs (hence the notion of "disposable" smart-contract).
What do you think? Is this even technically possible?
If yes, would it work a bit like my pseudo code or am I completely off?
I got the answer to my question via another channel: it's not recommendable to use this technique because the seller needs to sign the transaction for execution without knowing the contract address which will be executing the trade. So it would be like writing a blank check and comes with many security issues.
Related
I am building a scraper to get all Swap data from Uniswap using web3js.
So far I subscribe to the log and filter topics by Swap() event.
then I decode the data and get amount0In, amount1In, amount0Out, amount1Out.
My problem is in the swapExactETHForTokensSupportingFeeOnTransferTokens() function.
Normally a swap has token0 in and token1 out, but this function gives me values for 3 of the 4 and I can not seem to understand how to handle that. eventually what I want is to know what they spend, what they got and what I need to update the new reserves of that pair.
If someone has the understanding of the Uniswap RouterV2 contract swap functions, I would like to get some pointers on how to handle the data to get my calculations right.
I found the solution here ethereum.stackexchange Anyone with the same question gets a very detailed answer there.
some contracts actually transfers to recipient specified amount of tokens minus 10% (5% tax fee and 5% liquidity fee) 208940457743532637 - 10% = 188046411969179375 and emits Transfer event. Then, PancakePair _swap function emits Swap event with base value of Amount0Out 208940457743532637
Amount0In is greater than zero because the token contract returns part of tokens as a liquidity pair on Pancake Swap.
I am using web3-eth-contract package to connect to contract on Ethereum. I am executing it's methods by:
contract.methods
.methodName(ids)
.send({
to: address,
from: address
})
The problem is that I get:
After that I tried to add gasLimit there:
contract.methods
.methodName(ids)
.send({
to: address,
from: address,
gasLimit: 300000,
})
and it worked fine when I use methods that require only simple arguments. When I use methods where I pass array of arguments and there are more arguments than 2 transactions are being cancelled. What should I pass to gasLimit or how can I estimate it so it will work every time?
The gas used to execute the transaction may depend on your parameters, so what you experience is totally reasonable.
Now, to know what gasLimit to set you need to know what the transaction is doing and how much gas it is expected to burn. You can take one of the following approaches:
set the gasLimit very high, so that your transaction is always executed
check the older transactions to the same contract and see how much gas they burnt
use the transaction format after the London Uprade and specify max ETH you are willing to pay for the transaction (maxFeePerGas) instead of setting gasLimit
I am wondering besides these below mathematical expressions are there any other functions available to call inside a smart contract? Like math functions, like pi, sin, cosine, random() etc?
I am wondering if one can write smart contracts that require a little more than just basic arithmetic.
Below Image is taken from this page:
https://docs.soliditylang.org/en/develop/cheatsheet.html#function-visibility-specifiers
Solidity doesn't natively support storing floating point numbers both in storage and memory, probably because the EVM (Ethereum Virtual Machine; underlying layer) doesn't support it.
It allows working with them to some extent such as uint two = 3 / 1.5;.
So most floating point operations are usually done by defining a uint256 (256bit unsigned integer) number and another number defining the decimal length.
For example token contracts generally use 18 decimal places:
uint8 decimals = 18;
uint256 one = 1000000000000000000;
uint256 half = 500000000000000000;
There are some third-party libraries for calculating trigonometric functions (link), working with date time (link) and other use cases, but the native language currently doesn't support many of these features.
As for generating random numbers: No native function, but you can calculate a modulo of some pseudo-random variables such as block.hash and block.timestamp. Mind that these values can be (to some extent) manipulated by a miner publishing the currently mined block.
It's not recommended to use them in apps that work with money (pretty much most of smart contracts), because if the incentive is big enough, there can be a dishonest miner who can use the advantage of knowing the values before rest of the network and being able to modify them to some extent to their own benefit.
Example:
// a dishonest miner can publish a block with such params,
// that will result in the condition being true
// and their own tx to be the first one in the block that executes this function
function win10ETH() external {
if (uint256(blockhash(block.number)) % 12345 == 0) {
payable(msg.sender).transfer(10 ether);
}
}
If you need a random number that is not determinable by a miner, you can use the oracle approach, where an external app (called oracle) listens to transactions in a predefined format (generally also from&to specific addresses), performs an off-chain action (such as generating a random number, retrieving a google search result, or basically anything) and afterwards sends another transaction to your contract, containing the result of the off-chain action.
I see such code segment in proposer_task(xcom_base.c)
if(threephase || ep->p->force_delivery){
push_msg_3p(ep->site, ep->p, ep->prepare_msg, ep->msgno, normal);
}else{
push_msg_2p(ep->site, ep->p);
}
the threepahse is int const threephase = 0 and force_delivery == 0 here
push_msg_eq is normal paxos include prepare, accept and learn phase
but push_msg_2p will skip prepare phase and directly send accept request
I want to know why, Thanks a lot.
If you look at the paper Paxos Made Simple page 10 paragraph 3 says:
A newly chosen leader executes phase 1 for infinitely many instances
of the consensus algorithm [...]
Then paragraph 4:
Since failure of the leader and election of a new one should be rare
events, the effective cost of executing a state machine command—that
is, of achieving consensus on the command/value—is the cost of
executing only phase 2 of the consensus algorithm. It can be shown
that phase 2 of the Paxos consensus algorithm has the minimum possible
cost of any algorithm for reaching agreement in the presence of faults.
Hence, the Paxos algorithm is essentially optimal.
This is saying that a leader only issues a prepare during a leader failover. After that it streams accept messages. It then has "optimal messaging" in that the leader only needs one round trip to know a value is chosen (the accept message and its acknowledgment).
In a three node cluster, a leader self-accepts instantaneously, then only needs one accept acknowledgment from a second node to have a majority. It then knows the value is chosen without having to await the response from the 3rd node (which could be down). That is as efficient as you can get. The value is known to be accepted at a second node with strong consistency.
Given that is how paxos works to get maximum efficiency we should expect that mysql xcom has a mode that skips the prepare message phase in steady state.
You can read more about the Paxos Made Simple techniques on my blog here.
You might be interested to know about the latest developments of Paxos where you don't need a majority response for accept messages in the cluster using FPaxos and tricks like the even nodes optimization.
I have seen some transactions in etherscan.io.But I have found that even invoking the same function in the same smart contract, the gas used by txn are different.I try to found that maybe the input data result in it.Really?
The input data might be different, but also the state stored in the smart contract might be different (and change e.g. the number of times a loop iterates). Also, if storing nonzero data in a state variable that previously held zero data, or vice versa, will change the gas usage. For example, a simple function that toggles a boolean variable will not use the same amount of gas on any two consecutive calls.
Check out https://ethereum.stackexchange.com/ for future questions like this!
Each time you invoke a function in contract that requires state change in the block,it would cost x amount of gas , so every time you call different or same function in a contract that requires a state change,you would see that x amount of gas is being deducted along with its taxation Id.This is the reason you see different Txn on same function.
More about Gas and Transaction in the link below. http://solidity.readthedocs.io/en/develop/introduction-to-smart-contracts.html