I'm tryin to mint my ERC1155 nfts with my own ERC20 so i did the following :
1- created a variable of ERC20
ERC20 public FCG = FCG<br>
and in the constructor i pass the address of the ERC20 token contract
FCG = ERC20(0x0fC5025C764cE34df352757e82f7B5c4Df39A836);
2- in my mint function i did the following code
function mintCharacterPublic(address to, uint256 id, uint256 amount) public payable returns(bool){
require(to != address(0), "ERC1155: mint to the zero address");
require(FCG.approve(address(this), MINT_PRICE), "can't approve your token");
require(uint256(FCG.allowance(msg.sender, address(this))) >= MINT_PRICE, "Not enough of tokens");
FCG.transferFrom(msg.sender, address(this), MINT_PRICE);
mintCharacter(to, id, amount);
_balances[id][to] +=amount;
return true;
}
but when i try to mint it does not apply and it throws "Not enough of tokens"
so i think that the approve function does not function correctly.
here is my smart contract for the token
// SPDX-License-Identifier: MIT
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
pragma solidity ^0.8.2;
contract Token {
mapping(address => uint) public balances;
mapping(address => mapping(address => uint)) public allowance;
uint public totalSupply = 1000000 * 10 ** 18;
string public name = "FightClub Token";
string public symbol = "FCT";
uint public decimals = 18;
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
constructor() {
balances[msg.sender] = totalSupply;
}
function balanceOf(address owner) public view returns(uint) {
return balances[owner];
}
function transfer(address to, uint value) public returns(bool) {
require(balanceOf(msg.sender) >= value, 'balance too low');
balances[to] += value;
balances[msg.sender] -= value;
emit Transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint value) public returns(bool) {
require(balanceOf(from) >= value, 'balance too low');
require(allowance[from][msg.sender] >= value, 'allowance too low');
balances[to] += value;
balances[from] -= value;
emit Transfer(from, to, value);
return true;
}
function approve(address spender, uint value) public returns (bool) {
allowance[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
}
This must be a two-step process:
The user authorizes your contract to spend the token.
The user calls mintCharacterPublic.
Your contract cannot grant itself permission to spend the originator's tokens. require(FCG.approve(address(this), MINT_PRICE), "can't approve your token"); means that the eip-721 contract sets its own approval to MINT_PRICE, not the end-user's.
Related
I was searching for minimal ERC20 token implementation. The OpenZeppelin's ERC20 contract with all of these extension layers is too big for students tutoring
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
I wrote a TestERC20 smart-contract which implement IERC20 interface without inheritance.
It was used to test erc20-payment-gateway. I think that might be useful to the community too
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.7;
library Math {
function safeAdd(uint256 x, uint256 y) internal pure returns (uint256) {
uint256 z = x + y;
require(z >= x, "math-add-overflow");
return z;
}
function safeSub(uint256 x, uint256 y) internal pure returns (uint256) {
uint256 z = x - y;
require(z <= x, "math-sub-underflow");
return z;
}
}
contract TestERC20 {
uint256 public constant decimals = 18;
string public name;
string public symbol;
uint256 public totalSupply;
mapping (address => uint256) public balances;
mapping (address => mapping (address => uint256)) private allowances;
event Approval(address indexed src, address indexed usr, uint256 wad);
event Transfer(address indexed src, address indexed dst, uint256 wad);
function getChainId() public view returns(uint256) {
uint256 chainId;
assembly {
chainId := chainid()
}
return chainId;
}
constructor(string memory _symbol, string memory _name) {
symbol = _symbol;
name = _name;
}
function transfer(address dst, uint256 wad) external returns (bool) {
return transferFrom(msg.sender, dst, wad);
}
function transferFrom(address src, address dst, uint256 wad) public returns (bool) {
require(balances[src] >= wad, "nsufficient-balance");
if (src != msg.sender && allowances[src][msg.sender] != type(uint256).max) {
require(allowances[src][msg.sender] >= wad, "insufficient-allowances");
allowances[src][msg.sender] = Math.safeSub(allowances[src][msg.sender], wad);
}
balances[src] = Math.safeSub(balances[src], wad);
balances[dst] = Math.safeAdd(balances[dst], wad);
emit Transfer(src, dst, wad);
return true;
}
function mint(address usr, uint256 wad) public {
balances[usr] = Math.safeAdd(balances[usr], wad);
totalSupply = Math.safeAdd(totalSupply, wad);
emit Transfer(address(0), usr, wad);
}
function burn(address usr, uint256 wad) public {
require(balances[usr] >= wad, "insufficient-balance");
if (usr != msg.sender && allowances[usr][msg.sender] != type(uint256).max) {
require(allowances[usr][msg.sender] >= wad, "insufficient-allowances");
allowances[usr][msg.sender] = Math.safeSub(allowances[usr][msg.sender], wad);
}
balances[usr] = Math.safeSub(balances[usr], wad);
totalSupply = Math.safeSub(totalSupply, wad);
emit Transfer(usr, address(0), wad);
}
function approve(address usr, uint256 wad) external returns (bool) {
allowances[msg.sender][usr] = wad;
emit Approval(msg.sender, usr, wad);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return allowances[owner][spender];
}
function balanceOf(address account) public view returns (uint256) {
return balances[account];
}
}
Is it possible create a fee function that goes through desired wallet address in solidity?
if yes, can anybody tell me what's wrong with my code? coz my fee function doesn't work.
thanks in advance.
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.4;
contract Token {
mapping(address => uint) public balances;
mapping(address => mapping(address => uint)) public allowance;
uint public totalSupply = 1000000000 * 1e18;
string public name = "MAT COIN";
string public symbol = "MAT";
uint public decimals = 18;
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
constructor() {
balances[msg.sender] = totalSupply;
}
address admin = address(0x01FDD35e1263B9593fcf0ebd1f45415A22f1615d);
function transfer(address to, uint value) external returns (bool) {
uint256 fee = (value / 100) * 3; // Calculate 3% fee
balances[msg.sender] -= value; // subtract the full amount
balances[admin] += fee; // add the fee to the admin balance
balances[to] += (value - fee); // add the remainder to the recipient balance
emit Transfer(msg.sender, to, value);
return true;
}
function balanceOf(address owner) public view returns(uint) {
return balances[owner];
}
// function transfer(address to, uint value) public returns(bool) {
// require(balanceOf(msg.sender) >= value, 'balance too low');
// balances[to] += value;
// balances[msg.sender] -= value;
// emit Transfer(msg.sender, to, value);
// return true;
// }
function transferFrom(address from, address to, uint value) public returns(bool) {
require(balanceOf(from) >= value, 'balance too low');
require(allowance[from][msg.sender] >= value, 'allowance too low');
balances[to] += value;
balances[from] -= value;
emit Transfer(from, to, value);
return true;
}
function approve(address spender, uint value) public returns(bool) {
allowance[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
}
hope it's possible and sorry for a noob question.
I have designed an erc20 token and a smart contract to transfer that token, but when I trigger the function to transfer, the remix told me the following graph.
What I did was to deploy the token smart contract and then the DAO smart contract, then call the creatSubDAO function to start the transfer.
The relative code is below:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract Dtoken:
contract Dtoken is IERC20{
string public name = "DAO Token";
string public symbol = "D";
uint256 public totalSupply = 1000000000000000000000000;
uint8 public decimals = 18;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
constructor() {
balanceOf[msg.sender] = totalSupply;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value);
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= balanceOf[_from]);
require(_value <= allowance[_from][msg.sender]);
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
allowance[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
return true;
}
}
contract MasterDao:
import "./Dtoken.sol";
contract MasterDAO {
uint proposalNum;
mapping (address => Member) public members;
mapping (uint => Proposal) public proposals;
mapping (uint => SubDAO) public subDAOs;
// SubDAO[] public subDAOs;
function createSubDAO (uint _poolGap, uint _DAOID, uint _rate, Dtoken _token) public returns (address daoAddress) {
SubDAO subDAO = new SubDAO(_poolGap, _DAOID, msg.sender, _rate, this, _token);
daoAddress = address(subDAO);
}}
SubDao Contract:
contract SubDAO {
uint proposalNum;
address lender;
uint poolGap;
uint currentStake;
uint256 public DAOID;
MasterDAO master;
address stakeItem;
uint rate;
Dtoken public token;
mapping(address => Member) members;
mapping (uint => Proposal) public proposals;
string[] description;
event Transfrom(address, uint);
struct Member {
address memberAddress;
string nickName;
bool alreadyExist;
}
struct Proposal {
string description;
address payable recipient;
bool executed;
uint proposalID;
address[] agreeMembers;
address[] disagreeMembers;
bool exectuable;
uint amount;
Dtoken token;
}
modifier membership (MasterDAO masterDAO, address _staker){
require(masterDAO.addressExist(_staker) == true);
_;
}
modifier lenderLimit {
require(msg.sender == lender);
_;
}
modifier balanceLimit(uint amount) {
require(amount <= poolGap - currentStake);
_;
}
constructor (uint _poolGap, uint _DAOID, address _lender, uint _rate, MasterDAO caller, Dtoken _token) {
currentStake = 0;
poolGap = _poolGap;
DAOID = _DAOID;
lender = _lender;
master = caller;
rate = _rate;
token = _token;
token.transferFrom(address(this), address(this), 10);
}
Did I do anything wrong to transfer the token? Thanks!
From the SubDao constructor:
token.transferFrom(address(this), address(this), 10);
This snippet is trying to transfer tokens from the just created SubDao address (1st argument) to the very same address (2nd argument).
The newly created SubDao address most likely doesn't own any tokens to transfer from in the first place.
If you want to transfer tokens from the MasterDao to the newly created SubDao, you can remove the transferFrom() from the SubDao constructor, and implement the transfer in the MasterDao function createSubDAO():
function createSubDAO (uint _poolGap, uint _DAOID, uint _rate, Dtoken _token) public returns (address daoAddress) {
SubDAO subDAO = new SubDAO(_poolGap, _DAOID, msg.sender, _rate, this, _token);
daoAddress = address(subDAO);
// transfer 10 units of the `Dtoken`
// from the `MasterDao` address
// to the newly created `SubDao` address
// assuming that `MasterDao` has sufficient token balance
Dtoken(_token).transfer(daoAddress, 10);
}}
I made a solidity contract and when I compiled it, I got the following error: 'DeclarationError: Identifier not found or not unique. --> Token.sol:20:59: | 20 | function balanceOf(address owner) public view returns(unit) { | ^^^^' What's up with that?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
contract Token {
mapping(address => uint) public balances;
mapping(address => mapping(address => uint)) public allowance;
uint public totalSupply = 1000000 * 10 ** 18;
string public name = "Mebium";
string public symbol = "MEB";
uint public decimals = 18;
event Transfer(address indexed from, address indexed to, uint value);
event Approval (address indexed owner, address indexed spender, uint value);
constructor() {
balances[msg.sender] = totalSupply;
}
function balanceOf(address owner) public view returns(unit) {
return balances[owmer];
}
function transfer(address to, uint value) public returns(bool) {
require(balanceOf(msg.sender) >= value, 'balance too low');
balances[to] += value;
balances[msg.sender] -= value;
emit Transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint value) public returns(bool) {
require(balanceOf(from) >= value, 'balance too low');
require(allowance[from][msg.sender] >= value, 'allowance too low');
balances[to] += value;
balances[from] -= value;
emit Transfer(from, to, value);
return true;
}
function approve(address spender, uint value) public returns(bool) {
allowance[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
}
It's caused by a typo in your code. The return type should be uint (unsigned integer), not unit.
You have one more typo in the function - should be owner, is owmer.
function balanceOf(address owner) public view returns(uint) {
return balances[owner];
}
I have an ERC20 token (Cryptos) and want to send some tokens to VulnerableTokenSale smart contract, but it shows zero balance for the token balance (get_balanceToken function). Is it possible to do that? I am using Remix on Ethereum website.
contract VulnerableTokenSale {
address public wallet;
uint256 rate;
ERC20 public token;
address public owner;
mapping(address => uint256) public balances;
address [] beneficiaries;
modifier onlyOwner() {
require(msg.sender == owner, "not owner");
_;
}
constructor(address _wallet, uint256 _rate, ERC20 _token)
public {
wallet = _wallet;
rate = _rate;
token = _token;
owner = msg.sender;
}
function sendTokensWithRatio(uint256 _numerator, uint256 _denominator) external onlyOwner {
require(_numerator <= _denominator);
for(uint256 i = 0; i < beneficiaries.length; i++){
address beneficiary = beneficiaries[i];
uint256 balance = balances[beneficiary];
if(balance > 0) {
uint256 amount = balance * _numerator;
amount = amount / _denominator;
balances[beneficiary] = balance - amount;
token.transfer(beneficiary, amount);
}
}
}
function purchaseTokens() public payable{
uint256 weiAmount = msg.value;
uint256 _tokenAmount = weiAmount * rate;
beneficiaries.push(msg.sender);
balances[msg.sender] = balances[msg.sender] + _tokenAmount;
}
}
Think your constructor is slightly wrong, I have never seen anyone take in an ERC token directly.
I have something like this in my contracts:
constructor(address _wallet, uint256 _rate, address _tokenAddress) public {
wallet = _wallet;
rate = _rate;
token = ERC20(_tokenAddress);
owner = msg.sender;
}
Note you need the ERC20 interface for the above to work:
interface ERC20 {
function totalSupply() public view returns (uint);
function balanceOf(address tokenOwner) public view returns (uint balance);
function allowance(address tokenOwner, address spender) public view returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
// optional
function name() external view returns (string);
function symbol() external view returns (string);
function decimals() external view returns (string);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}