How can I transfer ERC20 token by another smart contract? - ethereum

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);
}}

Related

Minimal ERC20 contract for testing

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];
}
}

How to Mint ERC1155 with my own ERC20 token

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.

.balance method returning non-zero, while mapping (address => uint256) returning non-zero

I am trying to create a token on the BSC without reflections, with a simple flat fee for a dev wallet, and another fee for liquidity.
I am getting an error on every call to the following function:
function _transferStandard(address sender, address recipient, uint256 tAmount) private {
require(balanceOf(sender) > tAmount, "Insuficient balance for transaction.");
(uint256 tTransferAmount, uint256 fee) = _getValues(tAmount);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_tOwned[devWallet] = _tOwned[devWallet].add(fee);
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
emit Transfer(sender, recipient, tTransferAmount);
}
Subtraction is overflowing whenever tokens are removed from the senders wallet. Upon further analysis I discovered that the following function:
function balanceOf(address _owner) public view returns (uint256 balance){
return _owner.balance;
}
Will return a correct value of 1721391030000000000 for the owner balance (max supply is transfered to owner after deployment of the contract). However, the following function, which one would expect the same output from, is returning 0, as in the wallet has no balance.
function balanceOf_tOwned(address _owner) public view returns (uint256 balance){
return _tOwned[_owner];
}
_tOwned, on the other hand, is a simple mapping variable.
mapping (address => uint256) private _tOwned;
I am confused as to why balances appear as 0 when _tOwned is used.
Edit: I have now tested the dead wallet address 0x0000000000000000000000000000000000000000 for both functions. The results are diferent for both:
balanceOf returns: 10491075026009005720565 balanceOf_tOwned returns:
115792089237316195423570985008687907853269984665640000000000000000000000000000
I am again puzzled as to what this means, but possibly it is the mapping is actually returning the conversion to my token from BNB? I.e. its value of 380,000 USD in BNB (https://bscscan.com/address/0x0000000000000000000000000000000000000000).
Full contract code:
// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.12;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return payable(msg.sender);
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function transfer(address recipient, 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 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);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// The actual contract
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
renounceOwnership();
}
function owner() public view returns (address payable) {
return payable(_owner);
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
}
contract COOLCONTRACT is Context, IERC20, Ownable {
using SafeMath for uint256;
using Address for address;
mapping (address => uint256) private _tOwned;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private constant MAX = ~uint256(0);
uint256 _tTotal = 10 * 10**8 * 10**18;
uint256 private _rTotal = (MAX - (MAX % _tTotal));
string private _name = 'igb';
string private _symbol = 'yiibg';
uint8 private _decimals = 9;
constructor () {
_tOwned[owner()] = _rTotal;
}
// 80% donated, 20% used to fund the project
address payable private devWallet = payable(0x40C31d8F17338841FA1c8Af2F619B21428B1f358);
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _tTotal;
}
function balanceOf(address _owner) public view returns (uint256 balance){
return _owner.balance;
}
function shiet(address _owner) public view returns (uint256 balance){
return _tOwned[_owner];
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _approve(address owner, address spender, uint256 amount) private {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _transfer(address sender, address recipient, uint256 amount) private {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
_transferStandard(sender, recipient, amount);
}
function _transferStandard(address sender, address recipient, uint256 tAmount) private {
require(balanceOf(sender) > tAmount, "Insuficient balance for transaction.");
(uint256 tTransferAmount, uint256 fee) = _getValues(tAmount);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_tOwned[devWallet] = _tOwned[devWallet].add(fee);
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
emit Transfer(sender, recipient, tTransferAmount);
}
function _getValues(uint256 tAmount) private pure returns (uint256, uint256) {
uint256 fee = tAmount.div(100).mul(10);
uint256 totalTransac = tAmount.sub(fee);
return (totalTransac, fee);
}
}

Problem with sending ERC20 tokens from one smart contract to another one

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);
}

Identifier not found or not unique. Compilation errror

/home/ubuntu/token_sale/contracts/SandeepDappToken.sol:17:34: DeclarationError: Identifier not found or not unique.
function transfer(address _to, unit256 _value) public returns (bool success)
^—–^
Compilation failed. See below
code:
pragma solidity ^0.4.23;
contract SandeepDappToken
{
// constructor
// set the v ariable
uint256 public totalSupply;
string public name = ‘Dapp’;
mapping(address => uint256) public balanceOf;
constructor(uint256 _initialSupply ) public {
balanceOf[msg.sender] = _initialSupply;
totalSupply = _initialSupply;
}
function transfer(address _to, unit256 _value) public returns (bool success)
{
require(balanceOf[msg.sender] >= _value);
}
}
Change your code:
unit256 to uint256
function transfer(address _to, uint256 _value) public returns (bool success)