SimpleAirdrop contract deploy issue even compile is working - ethereum

I am trying to make Airdrop smartcontract but it return "This contract may be abstract, not implement an abstract parent's methods completely or not invoke an inherited contract's constructor correctly." message when deployed.....The compile works fine though.
Please check my code below
pragma solidity ^0.4.18;
contract ERC20 {
function transfer(address _to, uint256 _value)public returns(bool);
function balanceOf(address tokenOwner)public view returns(uint balance);
function transferFrom(address from, address to, uint256 tokens)public returns(bool success);
}
contract SimpleAirdrop is IERC20 {
IERC20 public token;
uint256 public _decimals = 18;
uint256 public _amount = 1*10**6*10**_decimals;
function SimpleAirdrop(address _tokenAddr) public {
token = IERC20(_tokenAddr);
}
function setAirdrop(uint256 amount, uint256 decimals) public {
_decimals = decimals;
_amount = amount*10**_decimals;
}
function getAirdrop(address reff) public returns (bool success) {
require (token.balanceOf(msg.sender) == 0);
//token.transfer(msg.sender, 1000000000000000000000);
//token.transfer(reff , 200000000000000000000);
token.transfer(msg.sender, _amount);
token.transfer(reff , _amount);
return true;
}
}

Your SimpleAirdrop inherits from IERC20 (see the first note). IERC20 is an abstract contract - it only defines its functions, but it doesn't implement them. Which makes SimpleAirdrop (the child contract of IERC20) an abstract contract as well.
Solidity doesn't allow deploying abstract contracts. So you have two options to make it not abstract:
Implement the transfer(), balanceOf() and transferFrom() functions (in any of the two contracts).
OR
Remove the inheritance, so that contract SimpleAirdrop is IERC20 becomes only contract SimpleAirdrop.
Assuming by the context of your SimpleAirdrop, which only executes functions on an external IERC20 address, but doesn't act as an ERC-20 token itself, option 2 is sufficient for your use case.
Notes:
Your question defines ERC20 contract but the rest of the code uses IERC20. I'm assuming this is just a typo while copying your code to the question, and that otherwise you're using the same naming in all places.
The current Solidity version (in June 2021) is 0.8.5. I recommend using the current version, there are security and bug fixes.

Please check for any misconception in codes below
No problem in compiling , Deployed using parameters and success in testnet
Problem rise when calling startAirdrop function...some problem with gas
Please be advised
pragma solidity ^0.4.18;
contract ERC20 {
function transfer(address _to, uint256 _value)public returns(bool);
function balanceOf(address tokenOwner)public view returns(uint balance);
function transferFrom(address from, address to, uint256 tokens)public returns(bool success);
}
contract SimpleAirdrop {
ERC20 public token;
uint256 public _decimals = 9;
uint256 public _amount = 1*10**6*10**_decimals;
uint256 public _cap = _amount *10**6;
address public tokenOwner = 0x0;
uint256 public _totalClaimed = 0;
uint256 public _reffPercent = 10;
function SimpleAirdrop(address _tokenAddr ,address _tokenOwner ) public {
token = ERC20(_tokenAddr);
tokenOwner = _tokenOwner;
}
function setAirdrop(uint256 amount, uint256 cap, uint256 decimals ,uint256 reffPercent) public returns (bool success){
require (msg.sender == tokenOwner);
_decimals = decimals;
_amount = amount*10**_decimals;
_cap = cap*10**_decimals;
_reffPercent = reffPercent;
return true;
}
function sendAirdropToken() public returns (bool success){
require (msg.sender == tokenOwner);
token.transferFrom(msg.sender,address(this),_cap);
return true;
}
function returnAirdropToOwner() public returns (bool success){
require (msg.sender == tokenOwner);
token.transferFrom(address(this), msg.sender, address(this).balance);
return true;
}
function getAirdrop(address reff) public returns (bool success){
if(msg.sender != reff && token.balanceOf(reff) != 0 && reff != 0x0000000000000000000000000000000000000000 && _cap >= _amount){
token.transfer(reff , _amount*(_reffPercent/100));
_cap = _cap - (_amount*(_reffPercent/100));
}
if(msg.sender != reff && token.balanceOf(reff) != 0 && token.balanceOf(msg.sender) == 0 && reff != 0x0000000000000000000000000000000000000000 && _cap >= _amount)
{ token.transfer(msg.sender, _amount);
_cap = _cap - _amount;
_totalClaimed ++;
}
return true;
}
}

Related

Despite using the receive() function, my contract is not receiving payment in Remix

I am writing a smart contract in Remix with Solidity. The purpose of the contract is to allow a user to mint an NFT for 1 ETH. At present, the user is able to mint and the contract accepts the payment (ie. the user's balance is properly subtracted). But when I check the address(this).balance of the contract with my accountBalance() function, the function returns 0. I have included the receive() function as per the Solidity docs:
event Received(address, uint);
receive() external payable {
emit Received(msg.sender, msg.value);
}
Can someone explain why this is happening and what I need to change about my contract? Here is my contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
// imports
import '#openzeppelin/contracts/token/ERC721/ERC721.sol';
import '#openzeppelin/contracts/access/Ownable.sol';
import '#openzeppelin/contracts/security/PullPayment.sol';
// contract
contract RobocopPoster is ERC721, Ownable, PullPayment {
// constants
uint256 public mintPrice;
uint256 public totalSupply;
uint256 public maxSupply;
uint256 public maxPerWallet;
bool public mintEnabled;
mapping (address => uint256) public walletMints;
// constructor
// initialize variables
constructor() payable ERC721('RobocopPoster', 'SFFPC') {
mintPrice = 1 ether;
totalSupply = 0;
maxSupply = 1000;
maxPerWallet = 3;
}
event Received(address, uint);
receive() external payable {
emit Received(msg.sender, msg.value);
}
// functions
function setMintEnabled(bool mintEnabled_) external onlyOwner {
mintEnabled = mintEnabled_;
}
function withdrawPayments(address payable payee) public override onlyOwner virtual {
super.withdrawPayments(payee);
}
function accountBalance() public view returns (uint256) {
return (address(this).balance);
}
function mint(uint256 quantity_) public payable {
require(mintEnabled, 'Minting not enabled.');
require(msg.value == quantity_ * mintPrice, 'wrong mint value');
require(totalSupply + quantity_ <= maxSupply, 'sold out');
require(walletMints[msg.sender] + quantity_ <= maxPerWallet, 'exceed max wallet');
walletMints[msg.sender] += quantity_;
_asyncTransfer(address(this), msg.value);
for (uint i = 0; i < quantity_; i++) {
uint256 newTokenId = totalSupply + 1;
totalSupply++;
_safeMint(msg.sender, newTokenId);
}
}
}
You need to call withdrawPayments to receive the fund, because _asyncTransfer from PullPayment in your contract minting sent the fund to the escrow contract. That's why you saw zero balance in ERC721 contract.

My "Buy" function in smart contract file keep making error

This is my solidity file for NFT marketplace.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract NFT is ERC721URIStorage,Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
address payable public _owner;
mapping(address => uint[]) public addressToTokenArray;
mapping(uint256 => bool) public forSale;
mapping(uint256 => uint256) public tokenIdToPrice;
event Minting(address _owner, uint256 _tokenId, uint256 _price);
event Purchase(address _seller, address _buyer, uint256 _price);
event Remove(uint256 _tokenId, uint[] beforeBuy, uint[] afterBuy);
constructor() ERC721("TeddyBear", "TEDDY") {
}
function mint(string memory _tokenURI, uint256 _price) public onlyOwner returns (bool)
{
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
tokenIdToPrice[newItemId] = _price;
if(addressToTokenArray[msg.sender].length !=1){
addressToTokenArray[msg.sender].push(newItemId);
}else{
addressToTokenArray[msg.sender] = [newItemId];
}
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, _tokenURI);
emit Minting(msg.sender, newItemId, _price);
return true;
}
// 토큰의 주인이 판매 하는 함수
function sell(uint256 _tokenId, uint256 _price) external {
require(msg.sender == ownerOf(_tokenId), 'Not owner of this token');
require(_price > 0, 'Price zero');
tokenIdToPrice[_tokenId] = _price;
forSale[_tokenId] = true;
}
// 토큰의 주인이 판매를 취하하는 함수
function stopSell(uint256 _tokenId) external {
require(msg.sender == ownerOf(_tokenId), 'Not owner of this token');
forSale[_tokenId] = false;
}
// function remove(uint[] memory array, uint index) public pure returns(uint[] memory) {
// if (index >= array.length) return array;
// for (uint i = index; i<array.length-1; i++){
// array[i] = array[i+1];
// }
// delete array[array.length-1];
// return array;
// }
function buy(uint256 _tokenId, uint256 sendAmount) external payable {
uint256 price = tokenIdToPrice[_tokenId];
bool isOnSale = forSale[_tokenId];
require(isOnSale, 'This token is not for sale');
require(sendAmount == price, 'Incorrect value');
address seller = ownerOf(_tokenId);
require(seller == ownerOf(_tokenId), 'Seller and Owner is not same');
// uint[] memory beforeBuy = addressToTokenArray[seller];
// // for(uint i=0;i<addressToTokenArray[seller].length;i++){
// // if(_tokenId == addressToTokenArray[seller][i]){
// // remove(addressToTokenArray[seller],i);
// // }
// // }
// uint[] memory afterBuy = addressToTokenArray[seller];
// emit Remove(_tokenId, beforeBuy, afterBuy);
addressToTokenArray[msg.sender] = [_tokenId];
safeTransferFrom(seller, msg.sender, _tokenId);
forSale[_tokenId] = true;
payable(seller).transfer(sendAmount); // send the ETH to the seller
emit Purchase(seller, msg.sender, sendAmount);
}
function getPrice(uint256 _tokenId) public view returns (uint256){
uint256 price = tokenIdToPrice[_tokenId];
return price;
}
function isSale(uint256 _tokenId) public view returns (bool){
bool isOnSale = forSale[_tokenId];
return isOnSale;
}
function getMyTokenId() public view returns (uint[] memory){
uint[] memory myTokens = addressToTokenArray[msg.sender];
return myTokens;
}
}
Among functions up there, the buy function does not emit an error when I compile the .sol file, but after I deploy this contract and send transaction for "buy" function it keeps making this error.
I just want to know where I should fix it and if there is any better idea for other functions, feel free to let me know... many thanks
Most likely it is failing here:
safeTransferFrom(seller, msg.sender, _tokenId);
If you check the ERC721 contract, safeTransferFrom eventually calls this:
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// ****** HERE IS THE ISSUE *****
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
If your contract is going to transfer a token on behalf of owner, owner has to approve first.
so from the seller's contract, this should be called:
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
tokenApprovals is a mapping that keeps track of which tokens can be transferred.
Debugging
in order to test which function call is causing error, place this requirement statement require(sendAmount == price, 'Incorrect value'); right before the function. and pass an incorrect value and you will get an error : 'Incorrect value'
Then put that require statement after the function, and pass a wrong value, if this require does send you error, you can be sure that function is causing the error

Type is not callable for openZeppelin function

pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol";
contract SharedWallet is Ownable {
mapping(address => uint) public allowance;
modifier ownerOrAllowed(uint _amount) {
require(onlyOwner() || allowance[msg.sender] >= _amount, "You are not allowed");
_;
}
function addAllowance(address _who, uint _amount) public ownerOrAllowed(_amount) {
allowance[_who] = _amount;
}
function withdrawMoney(address payable _to, uint _amount) public onlyOwner{
_to.transfer(_amount);
}
receive() external payable {
}
}
Hello I'm getting a error when I try to deploy this contract it's saying the type is not callable and is pointing at the onlyOwner() inside the modifier. I'm using openZeppelin and it has a modifier called onlyOwner() so this should work? I been trying to find the problem but can't.
It's not possible to call a modifier (in your case onlyOwner()) as a function.
You can do a workaround by copying the onlyOwner contents and using them in your ownerOrAllowed.
// replace `onlyOwner()` call to its contents: `owner() == _msgSender()`
modifier ownerOrAllowed(uint _amount) {
require(owner() == _msgSender() || allowance[msg.sender] >= _amount, "You are not allowed");
_;
}

Solidity: TypeError: Function declared as view, but this expression modifies the state and thus requires non-payable (the default) or payable

I have been trying to create a smart contract/Token, will deploy this on the Binance Smart Chain test net. I followed some documentation and started with this. I am getting into this function issue. Function is declared as Read only. Here is the source code
The function is changing the state of the Owner Address, what is the other option to declare it as read only
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.2;
//import "Context.sol";
//import "IBEP20.sol";
//import "SafeMath.sol";
//import "Ownable.sol";
contract SampleTaken {
mapping(address => uint) public balances;
uint public totalSupply = 1000000 * 10 ** 18;
string public name ="Sample Token";
string public symbol ="KJA";
uint public decimals = 18;
/** Events aailable for the Contract**/
event Transfer(address indexed _from, address indexed _to, uint256 _value);
constructor(){
balances[msg.sender] = totalSupply;
}
function balanceOf(address _ownerAddress) public view returns (uint){
return balances[_ownerAddress];
}
function transfer(address _toAddress, uint _noOfTokens) public view returns (bool){
require(balanceOf(msg.sender) >= _noOfTokens, "Total balance is less than the number of Tokens asked for !!!");
balances[_toAddress] +=_noOfTokens;
balances[msg.sender] -= _noOfTokens;
emit Transfer(msg.sender,_toAddress, _noOfTokens);
return true;
}
function transferFrom(address _from, address _to, uint _value) public returns (bool){
require(balanceOf(_from) >= _value, "Balance is less than the number of Tokens asked for !!!");
// require(allowance[_from][msg.sender] >= _value, "Allowance too low");
balances[_to] += _value;
balances[_from] -= _value;
emit Transfer (_from, _to, _value);
return true;
}
}
Any help is much appreciated.
Regards
Your transfer() function is declared as a view function.
Functions can be declared view in which case they promise not to modify the state.
Source: Solidity docs
But these lines (within the transfer() function) modify the state:
balances[_toAddress] +=_noOfTokens;
balances[msg.sender] -= _noOfTokens;
emit Transfer(msg.sender,_toAddress, _noOfTokens);
If you want your function to modify the state, it cannot be a view (nor a pure) function - and you need to remove the view modifier:
function transfer(address _toAddress, uint _noOfTokens) public returns (bool){
Remove view or pure keyword from the function declaration and keep only public returns
Change
function transfer(address _toAddress, uint _noOfTokens) public view returns (bool)
to
function transfer(address _toAddress, uint _noOfTokens) public returns (bool)
Changed method:
function transfer(address _toAddress, uint _noOfTokens) public returns (bool){
require(balanceOf(msg.sender) >= _noOfTokens, "Total balance is less than the number of Tokens asked for !!!");
balances[_toAddress] +=_noOfTokens;
balances[msg.sender] -= _noOfTokens;
emit Transfer(msg.sender,_toAddress, _noOfTokens);
return true;
}

Gas required exceeds block gas limit fallback function

I'm working on a smart contract and followed this video here: https://www.youtube.com/watch?v=s677QFT6e4U&t=911s. I copied the code exactly, but when I try to call the fallback function I get the following error: Gas required exceeds block gas limit: 300000000. Even though the fallback function is as follows (it does nothing):
function () payable {
}
How could this be using too much gas?
CONTRACT CODE:
pragma solidity ^0.4.11;
import './IERC20.sol';
import './SafeMath.sol';
contract AToken is IERC20 {
using SafeMath for uint256;
uint256 public _totalSupply = 0;
uint256 public constant hardLimit = 45000000;
string public constant symbol = "ABC";
string public constant name = "Alphabet";
uint8 public constant decimals = 18;
//1 ETH = 25000 Alphabet
uint256 public constant RATE = 25000;
address public owner;
mapping(address => uint256) balances;
mapping(address => mapping(address => uint256)) allowed;
function () payable {
createTokens();
}
function SnapToken() {
owner = msg.sender;
}
function createTokens() payable {
//require(msg.value > 0);
//uint256 tokens = msg.value.mul(RATE);
//require(tokens.add(_totalSupply) <= hardLimit);
//balances[msg.sender] = balances[msg.sender].add(tokens);
//_totalSupply = _totalSupply.add(tokens);
//owner.transfer(msg.value);
}
function totalSupply() constant returns (uint256 totalSupply) {
return _totalSupply;
}
function balanceOf(address _owner) constant returns (uint256 balance) {
return balances[_owner];
}
function transfer(address _to, uint256 _value) returns (bool success) {
require(balances[msg.sender] >= _value && _value > 0);
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
require(allowed[_from][msg.sender] >= _value && balances[_from] >= _value && _value > 0);
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
Transfer(_from, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) returns (bool success) {
//allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_value);
Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 value);
}
I commented out some stuff to see if this would reduce the gas requirement but unfortunately not. Have you faced this before?
Thanks
The contract, as posted, does execute when calling the fallback function (Tested in Remix). However, it will fail once you uncomment the logic in createTokens()
Fallback functions have low gas limits (2300) and, therefore, are very limited in what they can do. You can't do things like write to storage, call external functions, or send ether out as you will instantly hit the limit. It should primarily be used to enable your contract to receive ether and maybe log an event.
In the example you posted above, remove the call to createTokens() in your fallback function and just call that function directly from your client.
Documentation on Fallback Functions
Example client code:
const abiDefinition = ...;
const contractAddress = ...;
const account = ...;
const amountInEther = ...;
const contract = web3.eth.contract(abiDefinition);
const contractInstance = contract.at(contractAddress);
const transactionObj = {
from: account,
value: web3.toWei(amountInEther, 'ether'),
};
contractInstance.createTokens.sendTransaction(transactionObj, (error, result) = {
...
};
Also, as a side note, your value calculations are incorrect. msg.value is in Wei, not ether. Sending in 1 ether causes you to go well above your hardlimit. It's recommended to work with Wei in your contracts, so you should adjust your RATE.