I've played around for some bit with a selfmade program. I just tried to sell some random token on uniswap which I bought earlier. My transaction somehow didn't go through and I don't know why.
https://etherscan.io/tx/0xcb4ef6baab722e00e6dad75d12398fc88cc5177445758064a14c8433612a860f
Does someone have an Idea why it didn't go through, I'm not familiar enough with the solidity/ethereum yet.
Thanks a lot in advance.
We can check which require the transaction failed to meet by searching for the message in contract TRANSFER_FROM_FAILED.
The function calls transferFrom function. transferFrom function requires the owner of the token to approve a spender to spend on his/her behalf.
Seems like you have not approve the spender to spend on your behalf.
You can check more info regarding transferFrom at this docs
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
swapExactTokensForETH uses safeTransferFrom function
...
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
UniswapV2Library.pairFor(factory, path[0], path[1]),
amounts[0]
);
...
Related
I want to make new coin in solidity.
I found the code how to make subsidy halving in Bitcoin clone coding.
Can I make subsidy halving in solidity?(ERC-20, 721, 1155 whatever)
I can't find any subsidy halving in ERC coin.
Sorry for my poor English.
I want to assume that you mean: "Bitcoin Halving." Given that is the case, in Solidity, what is available is: "Token burning".
To ensure that you understand: Bitcoin Halving is an event that occurs where the block reward given to Bitcoin miners for processing transactions is cut in half.
Token Burning in Ethereum is a way of removing tokens from circulation by sending the tokens to a "dead address" this renders the token "unspendable." This is often done to reduce the amount of the said token in circulation. This ultimately affects the token liquidity.
The simple function below illustrates Polygon MATIC token burning:
function _burn(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.sub(value);
_balances[account] = _balances[account].sub(value);
emit Transfer(account, address(0), value);
}
The above function is part of the functions deployed when initializing a token contract in solidity. With this function as part of the deployed contract code, you can burn any token type: ERC20, ERC721 ...
You will find this resource useful to understand more: https://academy.binance.com/en/articles/what-is-a-coin-burn
I'm working on a uni project based on blockchain, and I have to audit our system, check known attacks, ect.
This the the document that I check, principaly, since i start to work on smart contracts issues first :
Known-attack ethereum smart contract
I have trouble understanding the example used in the "Dos With (unexpected) revert attack" part. I share the code :
// INSECURE
contract Auction {
address currentLeader;
uint highestBid;
function bid() payable {
require(msg.value > highestBid);
require(currentLeader.send(highestBid)); // Refund the old leader, if it fails then revert
currentLeader = msg.sender;
highestBid = msg.value;
}}
They say that an attacker could force the call of bid to revert everytime so no-one is able to bid, which would make the attacker win the auction by default.
But.. How would he do that, that's the part I don't get. Do we agree that at least this piece of contract is the "valid one", and isn't a payload ? If the payload is a contract, can anyone provide an exemple/explanation ?
I'll add that, if here I quote a solidity contract, we work with Vyper, but from what I read before, this is still a kind of issue that i'll find there too.
Thanks in advance !
If send() target address is a smart contract it will execute the fallback function.
If the currentLeader points to a smart contract that has a fallback function that has been intentionally made to revert on failed send, the bid() won't work for any participants until currentLeader has been changed.
More information here.
This is not a "DoS" attack but simply gotcha in Solidity programming.
I am trying to implement this Airdrop: https://github.com/odemio/airdropper/blob/master/Airdropper.sol
Initially, I started writing tests for our use-case, but the airdrop was not working.
function airdrop(address source, address[] dests, uint[] values) public onlyOwner {
// This simple validation will catch most mistakes without consuming
// too much gas.
require(dests.length == values.length);
for (uint256 i = 0; i < dests.length; i++) {
require(token.transferFrom(source, dests[i], values[i].mul(multiplier)));
}
}
Then I moved to Remix to goe through the whole airdrop process, including our Contract deployment, token minting and allowance.
In Remix debugger I found out that the issue is on the line
require(token.transferFrom(source, dests[i], values[i].mul(multiplier)));
I also tested the transferFrom function directly on our contract using the same values on Remix.
The error I get when trying to airdrop is:
transact to Airdrop.airdrop errored: VM error: revert.
revert The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value. Debug the transaction to get more information.
What could cause this issue and how can I debug this further? :)
Thanks and have a nice day!
The error could be for several reasons:
source doesn’t have enough tokens to cover all of the transfers.
One or more destination addresses are invalid.
The approve wasn’t done correctly (it’s the airdrop contract that needs to be approved, not the initiator of the transaction).
You can narrow it down by removing the require and see if any drops are successful (the way you have it coded, one failure will roll back the entire transaction).
I just started learning solidity and have some questiones about the smart contract I created for pratice/fun.
Please let me know if any of my concepts are inaccurate, appreciate for all the advices and suggestiones.
Description:
the concept of this smart contract is really simple, whoever send the bigger amount of ether into the contract wins, it will pair you with whoever is before you (if no one is before you, you are player_one) and it will reset after 2 player are played (so it can be played again)
Code:
contract zero_one {
address public player_one;
address public player_two;
uint public player_one_amount;
uint public player_two_amount;
function zero_one() public{
reset();
}
function play() public payable{
//Scenario #1 Already have two player in game, dont accpet new player. do I even need this check at all? since smart contract execute serially i should never face this condition?
if(player_one != address(0) && player_two != address(0)) throw;
//Scenario #2 First player enter the game
else if(player_one == address(0) && player_two == address(0)){
player_one=msg.sender;
player_one_amount = msg.value;
}
//Scenario #3 Second player join in, execute the game
else{
player_two = msg.sender;
player_two_amount = msg.value;
//check the amount send from player_one and player two, whoever has the bigger amount win and get their money
if(player_two_amount>player_one_amount){
player_one.transfer(player_one_amount+player_two_amount);
reset();
}
else if(player_two_amount<player_one_amount){
player_two.transfer(player_one_amount+player_two_amount);
reset();
}
else{
//return fund back to both player
player_one.transfer(player_one_amount);
player_two.transfer(player_two_amount);
reset();
}
}
}
function reset() internal{
player_one = address(0);
player_two = address(0);
player_one_amount = 0;
player_two_amount = 0;
}
}
Questions
When sending ether back to users, do I need to calcualate how much
gas is going to take? or would smart contract automatically deduct
the gas from the amount i am going to send
Is it correct to set reset() as interal since i only want it to be
called within the smart contract, it shouldn't be called by anyone else
Would Scenario#1 ever happen? since from what I understand
smart contract do not have to worry about race condition and it
should never be in that state?
Is adding playable to play correct? ( since user are going to send ether with this call)
Is using throw a bad practice? (warning on remix)
transfer vs send, why is it better to use transfer?
I coded this smart contract as a practice. I can already see that if
someone want to game the system, he could just wait for someone to be player_one and check the amount player_one send(after the block is mined) and just send a bigger sum than that. Is there anyway this exploit could be stopped? Is there other security/flaws I did not see?
Thanks!
When sending ether back to users, do I need to calcualate how much gas
is going to take? or would smart contract automatically deduct the gas
from the amount i am going to send
The gas limit specified when executing a transaction needs to cover all activity end-to-end. This includes calls out to other contracts, transfers, etc. Any gas not used after the transaction is mined is returned to you.
Is it correct to set reset() as interal since i only want it to be
called within the smart contract, it shouldn't be called by anyone
else
internal is fine for what you're intending to do. But, it's more like protected access. A sub-contract can call internal methods. private provides the strictest visibility.
Would Scenario#1 ever happen? since from what I understand smart
contract do not have to worry about race condition and it should never
be in that state?
No, it should not happen. You are correct that transactions are processed serially, so you don't really have to worry about race conditions. That doesn't mean you shouldn't have this sort of protection in your code though...
Is adding playable to play correct? ( since user are going to send
ether with this call)
Yes. Any method that is expecting to receive wei and uses msg.value needs to be marked as payable.
Is using throw a bad practice? (warning on remix)
throw is deprecated. You want to use one of revert, require, assert as of 0.4.13. The one you use depends on the type of check you're doing and if gas should be refunded. See this for more details.
transfer vs send, why is it better to use transfer?
send and transfer are similar. The difference is that send limited the amount of gas sent to the call, so if the receiving contract tried to execute any logic, it would most likely run out of gas and fail. In addition, failures during send would not propagate the error and simply return false. Source
I coded this smart contract as a practice. I can already see that if
someone want to game the system, he could just wait for someone to be
player_one and check the amount player_one send(after the block is
mined) and just send a bigger sum than that. Is there anyway this
exploit could be stopped? Is there other security/flaws I did not see?
Security is a much more in depth topic. Any data sent in a transaction is visible, so you can't hide the exploit you mentioned unless you use a private blockchain. You can encrypt data sent in a transaction yourself, but I don't believe you can encrypt sending ether.
In terms of other security issues, there are several tools out there that perform security checks on contracts. I'd suggest looking into one of those. Also, read through the security considerations page on the Solidity documentation.
An address in Solidity can be an account or a contract (or other things, such as a transaction). When I have a variable x, holding an address, how can I test if it is a contract or not?
(Yes, I've read the chapter on types in the doc)
Yes you can, by using some EVM assembly code to get the address' code size:
function isContract(address addr) returns (bool) {
uint size;
assembly { size := extcodesize(addr) }
return size > 0;
}
The top-voted answer with the isContract function that uses EXTCODESIZE was discovered to be hackable.
The function will return false if it is invoked from a contract's constructor (because the contract has not been deployed yet).
The code should be used very carefully, if at all, to avoid security hacks such as:
https://www.reddit.com/r/ethereum/comments/916xni/how_to_pwn_fomo3d_a_beginners_guide (archive)
To repeat:
Do not use the EXTCODESIZE check to prevent smart contracts from calling a function. This is not foolproof, it can be subverted by a constructor call, due to the fact that while the constructor is running, EXTCODESIZE for that address returns 0.
See sample code for a contract that tricks EXTCODESIZE to return 0.
Checking if a caller is a contract
If you want to make sure that an EOA is calling your contract, a simple way is require(msg.sender == tx.origin). However, preventing a contract is an anti-pattern with security and interoperability considerations.
require(msg.sender == tx.origin) will need revisiting when account abstraction is implemented.
Checking if a callee is a contract
As #Luke points out in a comment, there is no general on-chain way to find out about a callee. If you want to "call" an address, there's no general way to find out if that address is a contract, EOA, or an address that a new contract can be deployed on, or if it's a CREATE2 address.
One non-general way that works for some callees: you can have a mapping on-chain that stores addresses of known EOAs or contracts. (Just remember that for an address without any on-chain history, you can't know if it's an EOA or an address that a contract can be deployed on.)
This isn't something you can query from within a contract using Solidity, but if you were just wanting to know whether an address holds contract code or not, you can check using your geth console or similar with eg:
> eth.getCode("0xbfb2e296d9cf3e593e79981235aed29ab9984c0f")
with the hex string (here 0xbfb2e296d9cf3e593e79981235aed29ab9984c0f) as the address you wish to query. This will return the bytecode stored at that address.
You can also use a blockchain scanner to find the source code of the contract at that address, for example the ecsol library as shown on etherscan.io.
Edit: Solidity has changed since this answer was first written, #manuel-aráoz has the correct answer.
There is no way in solidity to check if an address is a contract. One of the goals of Ethereum is for humans and smart contracts to both be treated equally. This leads into a future where smart contracts interact seamlessly with humans and other contracts. It might change in the future , but for now an arbitrary address is ambiguous.
If you want to use nodejs to confirm, you can do this:
const Web3 = require('web3')
// make sure you are running geth locally
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'))
is_contract = async function(address) {
res = await web3.eth.getCode(address)
return res.length > 5
}
is_contract('your address').then(console.log)
From openzeppeling Address.sol library, it has this function:
pragma solidity ^0.8.1;
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
isContract will return false for the following types of addresses:
an externally-owned account
a contract in construction
an address where a contract will be created
an address where a contract lived, but was destroyed
What you can do, granted you have the information at hand.
If the transactions sender address was null or unoccupied then you can tell if the address is a contract account or an EOA (externally owned account).
i.e. when sending a create contract transaction on the network then the receive address in the transaction is null/not used.
Reference from github:
https://github.com/ethereum/go-ethereum/wiki/Contracts-and-Transactions
Hope this helps.
If you are checking whether the caller is an EOA rather than a contract:
Short answer:
require(tx.origin == msg.sender);
tx.origin is a reference of the original address who initiates this serial function call, while msg.sender is the address who directly calls the target function. Which means, tx.origin must be a human, msg.sender can be a contract or human. Thus, if someone calls you from a contract, then the msg.sender is a contract address which is different from tx.origin.
I know most contracts may use #Manuel Aráoz's code, which works in most cases. But if you call a function within the constructor of a contract, extcodesize will return 0 which fails the isContract check.
NOTE: DON'T use tx.origin under other circumstances if you are not clear about what it represents because .