We have created a proxy contract that mints an NFT on our existing contract, as no to parameter was originally provided.
Everything works fine, however, once done and the NFT is shown on Crossmint we cannot transfer the NFT into another wallet. The following error is shown:
The successful mint transaction was this one: https://rinkeby.etherscan.io/tx/0x700cd7572303770232587ad04c65bb8b8d56f33e00ccd6d8df0980710380bd60
The proxy contract is this one:
https://rinkeby.etherscan.io/address/0xC36DB9076D0F662c9945fbd005Ea260B5259521c
Any idea what is going wrong here?
Something that might be worth looking into is your crossmint method as I think there may be an issue with how the logic is layed out in here.
One thing you might look at is the line where you attempt to transfer your token. Your from parameter is using address(this) which is actually referring to your proxy address and not your oefbContract address. I would change this to your original contract address and see if this makes a difference.
function crossmint(address to, uint8 amount) external payable {
uint256 total = oefbContract.totalSupply();
oefbContract.mintNFT{value: msg.value}(amount);
for (uint256 i = 0; i < amount; i++) {
oefbContract.transferFrom(address(this), to, total + i);
}
}
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'm traying to swap some DAI for ETH on the Ropsten Network using the UniswapV2Router02 on Etherscan (Ropsten Test Network).
DAI Address on Ropsten = 0xad6d458402f60fd3bd25163575031acdce07538d
WETH = 0xc778417E063141139Fce010982780140Aa0cD5Ab
in my Wallet i have 2000 DAI (Ropsten)
but when i put the data there. like this:
Metamask shows that there is an Error thrown by the Contract.
So i might be missing something or am'i doing it wrong.
can please someone help and show me how can i make a successful transaction there ?
i got this to work.
if someone is interested to know how, here is what i have done.
1- amountIn should be in 10^18, that means 100 was wrong, it should be 100x10^18 = 100000000000000000000
2- first i had to approve the UniswapRouterAddress to spend this 100 DAI.
so on the DAI contract Address i had to put the data like this:
after that i was able t swap the 100 DAI for ETH (as much as 100 DAI is worth of ETH)
I'm trying to deploy the following contract on Ropsten using an injected web3 environment (i.e. metamask) on remix.ethereum.org/
pragma solidity ^0.4.16;
contract Coin {
// The keyword "public" makes those variables
// readable from outside.
address public minter;
mapping (address => uint) public balances;
// Events allow light clients to react on
// changes efficiently.
event Sent(address from, address to, uint amount);
// This is the constructor whose code is
// run only when the contract is created.
function Coin() public {
minter = msg.sender;
}
}
I've been able to create contracts with ease using remix before. I'm not sure what has changed, but I can't create contracts at all because of the gas limit thing. I've even gone as far as setting the gas limit to 2 full Ethers (i.e. value 1 ether with max of 2). I have close to 3 ethers in my metamask wallet. The remix "Account" dropdown also displays my metamask address correctly so it seems that the injected environment is connected.
When I try to create this contract I can't get past the gas required exceeds limit 2 error. I'm scratching my head as to why this simple contract would exceed the cost of 2 full Ethers.
Other parameters for remix in use:
optimize=false&version=soljson-v0.4.20+commit.3155dd80.js
Is there a setting on remix that I've forgotten? I'm Trying to deploy this from Chrome.
edit: I'm still scratching my head on this one. I was able to create the contract above for a brief moment after refreshing my page, but I came in today to try and run the code from https://www.ethereum.org/token and I can't get past the exceeds gas error with a value of 20 Gwei and a limit of 3000000. Note, I tried using the simple sample contract above and I'm back to where I was when I started - even the simple "Coin" contract above apparently exceeds the gas limit.
edit 2: Well, I think I'm getting somewhere. I've changed the compiler version from "soljson-v0.4.20+commit.3155dd80.js" to "soljson-v0.4.19+commit.c4cbbb05.js". Then I refresh the page 3 times. After that I wait a couple of minutes and things seem to be working again. There is something else happening here because when I reject the transaction in metamask and then return to remix to create again, I encounter the gas exceeded error. I don't believe the issue here is metamask as I've tried to connect locally using testrpc - localhost:8545 - and experience the same issue. All I can say is that the same code that I try to create fails to submit because of the gas error most of the time but occasionally works regardless of compiler version.
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 .