ERC20 Payment processing - blockchain

What's wrong with my smart contract, because I get "Error: cannot estimate gas; transaction may fail or may require manual gas limit". On frontend I am calling approveTokens() first and acceptPayment() later
pragma solidity ^0.8.11;
import '#openzeppelin/contracts/token/ERC20/IERC20.sol';
contract PaymentProcessor {
address public owner;
IERC20 public token;
constructor(address _owner, address _token) {
owner = _owner;
token = IERC20(_token);
}
event PaymentCompleted(
address payer,
uint256 amount,
uint paymentId,
uint timestamp
);
function approveTokens(uint256 amount) public returns(bool){
token.approve(owner, amount);
return true;
}
function getAllowance() public view returns(uint256){
return token.allowance(msg.sender, owner);
}
function acceptPayment(uint256 amount, uint paymentId) payable public {
require(amount > getAllowance(), "Please approve tokens before transferring");
token.transfer(owner, amount);
emit PaymentCompleted(msg.sender, amount, paymentId, block.timestamp);
}
}

Users need to call approve() directly on the token address - not through your contract.
Your current implementation approves owner to spend PaymentProcessor's tokens because PaymentProcessor is the msg.sender in the context of the token contract.

Related

Solidity - Execution reverted (how to debug in Remix)

I am creating blockchain lottery smart contract that is using my own ERC20 token.
The idea is simple. Players buy any amount of tickets they want. Each ticket that is bought is stored as a pair of address and ticketId.
When the manager calls the pickWinner() function, a random number is generated and one ticket is chosen as the winning one.
All is working good until I call the pickWinner() function. After I try to call it I get the following error:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted { "originalError": { "code": 3, "data": "0x4e487b710000000000000000000000000000000000000000000000000000000000000032", "message": "execution reverted" } }
The problem is, it's not telling me where the problem is. I don't know how to proceed further without trying removing line by line and see where's the problem.
Here's the code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract Lottery {
event TicketsBought(address playerAddress, uint256 quantity, uint256 ticketPrice);
event WinnerPicked(ticket ticket, uint256 amount);
struct ticket {
address walletAddress;
uint256 ticketId;
}
uint256 currentTicketId = 0;
address gamblinoAddress = 0xE9FEA6A6A1a8BB99E0C888c93A06D22f804A5fFA;
uint public ticketPrice = 50 * 10**18;
address public manager;
ticket public winner;
ticket[] public tickets;
uint256 public balance;
constructor() {
manager = msg.sender;
balance = 0;
}
function getPlayerAddresses() private view returns (address[] memory) {
address[] memory addresses;
for(uint i = 0; i < tickets.length; i++) {
addresses[i] = tickets[i].walletAddress;
}
return addresses;
}
function buyTickets(uint256 quantity) public payable {
uint256 amount = ticketPrice * quantity;
GamblinoToken gamblinoToken = GamblinoToken(gamblinoAddress);
uint256 allowance = gamblinoToken.allowance(msg.sender, address(this));
uint256 playerBalance = gamblinoToken.balanceOf(msg.sender);
require(playerBalance >= amount, 'Check token balance');
require(allowance >= amount, 'Check the token allowance');
balance = balance + amount;
for (uint i = 0; i < quantity; i++) {
ticket memory t = ticket(msg.sender, currentTicketId);
tickets.push(t);
currentTicketId++;
}
gamblinoToken.transferFrom(msg.sender, address(this), amount);
emit TicketsBought(msg.sender, quantity, ticketPrice);
}
function random() public view returns (uint) {
return uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp, getPlayerAddresses())));
}
function pickWinner() public {
uint index = random() % tickets.length;
uint256 amount = balance;
GamblinoToken gamblinoToken = GamblinoToken(gamblinoAddress);
// the entitre balance of this contract to the winner.
gamblinoToken.transfer(tickets[index].walletAddress, balance);
// set balance to 0
balance = 0;
// set winner
winner = tickets[index];
// reset ticket id
currentTicketId = 0;
// clear players and start over.
delete tickets;
emit WinnerPicked(winner, amount);
}
function getTickets() public view returns (ticket[] memory) {
return tickets;
}
// restrict to only the manager (the contract creator)
modifier restricted() {
require(msg.sender == manager);
_;
}
}
interface ERC20Interface {
function totalSupply() external view returns (uint256);
function balanceOf(address tokenOwner) external view returns (uint balance);
function allowance(address tokenOwner, address spender) external view returns (uint remaining);
function transfer(address to, uint tokens) external returns (bool success);
function approve(address spender, uint tokens) external returns (bool success);
function transferFrom(address from, address to, uint tokens) external returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
contract GamblinoToken is ERC20Interface {
function totalSupply() public override view returns (uint256) {}
function balanceOf(address tokenOwner) public override view returns (uint) {}
function transfer(address receiver, uint numTokens) public override returns (bool) {}
function approve(address delegate, uint numTokens) public override returns (bool) {}
function allowance(address owner, address delegate) public override view returns (uint) {}
function transferFrom(address owner, address buyer, uint numTokens) public override returns (bool) {}
}

Sending eth from one metamask wallet to another wallet in solidity

I'm trying to write a smart contract to transfer eth from one metamask wallet to another metamask wallet in solidity in remix with Injected Web 3 environment. I deployed the contract but the transaction send_ETH failed. Could anyone help me figure out why? Thank you so much
pragma solidity >=0.8.0;
// Get the latest ETH/USD price from chainlink price feed
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract myContract {
address payable[] recipients;
mapping(address => uint256) public balanceAccount;
address public owner;
constructor() {
owner = msg.sender;
}
function send_ETH(address payable recipient, uint256 amount) public {
//set the minimum amount of dollar to transfer
uint256 minimumUSD = 0.01 * 10 ** 18;
amount = minimumUSD;
require(getConversionRate(amount) >= minimumUSD, "You need to spend more ETH!");
this.invest(amount);
this.fund(recipient);
}
function invest(uint256 amount) payable external{
//transfer amount ETH from metadata wallet to smart contract
recordTransaction(address(this), amount, false);
recordTransaction(owner, amount, true);
address payable contractAddress = payable(address(this));
contractAddress.send(amount);
}
function fund(address payable recipient) external {
//transfer amount ETH from this smart contract to the recipient
recordTransaction(address(this), address(this).balance, true);
recordTransaction(recipient, address(this).balance, false);
recipient.send(address(this).balance);
}
function recordTransaction(address recipient, uint256 deposit, bool out) private {
if (out) {
balanceAccount[recipient] -= deposit;
} else {
balanceAccount[recipient] += deposit;
}
}
function getVersion() public view returns (uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
return priceFeed.version();
}
function getPrice() public view returns(uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
(,int256 answer,,,) = priceFeed.latestRoundData();
// ETH/USD rate in 18 digit
return uint256(answer * 10000000000);
}
function getConversionRate(uint256 ethAmount) public view returns (uint256){
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
// the actual ETH/USD conversation rate, after adjusting the extra 0s.
return ethAmountInUsd;
}
}
your function invest() is wrong
function invest(uint256 amount) payable external{
//transfer amount ETH from metadata wallet to smart contract
recordTransaction(address(this), amount, false);
recordTransaction(owner, amount, true);
//these 2 lines below are wrong
address payable contractAddress = payable(address(this));
contractAddress.send(amount);
}
You marked that function as payable, that's correct if you interact directly with that, but you interact with send_eth, so it needs to be payable to receive eth
Then you saved the contract address as payable and did contractAddress.send(amount) that's mean: "contract send 'amount' to contract"
the send() function send money from contract to an address
also the amount var is wrong
all eth sent are sent directly through tx information, and not through data
the function correct:
function send_ETH(address payable recipient) payable public {
//set the minimum amount of dollar to transfer
uint256 minimumUSD = 0.01 * 1e18;
require(getConversionRate(msg.value) >= minimumUSD, "You need to spend more ETH!");
this.invest(msg.value);
this.fund(recipient);
}
function invest() internal{
//transfer amount ETH from metadata wallet to smart contract
recordTransaction(address(this), amount, false);
recordTransaction(owner, amount, true);
}
then when calling send_eth you have to write manually the amount of eth to send, if you will make an interface for that, you can write the eth amount to send inside the tx details like:
const transaction = {
'to': '0x31B98D14007bDEe637298086988A0bBd31184523', //contract address
'value': 1, //1 eth
'gas': 30000,
'maxFeePerGas': 1000000108,
'nonce': nonce,
};

How to transfer ERC1155 token using web3js?

I am trying to transfer ERC1155 tokens to another account. I have deployed the contract and have put down my contract code below.
The problem I am facing is I get the below error when I call getMyToken function from my frontend web3js code.
{code: -32603, message: 'execution reverted: ERC1155: caller is not owner nor approved', data: {…}}
Not sure what is happening. I am calling the function as below from frontend. The isApproved function is returning true.
const selectedAccountIsApproved = await monkeysContract.methods.isApproved(selectedAccount).call();
console.log('IS APPROVED RESULT: ', selectedAccountIsApproved);
if(selectedAccountIsApproved) {
const result = await monkeysContract.methods.mintMyMonkey(selectedAccount, 0).call();
console.log('Transfer Result: ', result);
} else {
console.log('Account not approved by owner for transfers');
}
NOTE:
I have called the setApprovalForAll method and approved the receiver account.
I am able to call isApprovedForAll and verify that the account is approved.
I am able to transfer tokens to the receiver through Etherscan contract interface.
Contract Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "#openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract Monkeys is ERC1155, Ownable {
uint256 public constant CC1 = 0;
uint256 public constant CC2 = 1;
mapping (uint256 => string) private _uris;
constructor() public ERC1155("https://game.example/api/item/{id}.json") {
_mint(msg.sender, CC1, 1000, "");
_mint(msg.sender, CC2, 1000, "");
}
function uri(uint256 tokenId) override public view returns (string memory) {
return(_uris[tokenId]);
}
function setTokenUri(uint256 id, string memory url) public onlyOwner {
require(bytes(_uris[id]).length == 0, "Cannot set uri twice");
_uris[id] = url;
}
function transfer(address from, address to, uint256 id, uint256 amount, bytes memory data) public {
safeTransferFrom(from, to, id, amount, data);
}
function isApproved(address user) public view virtual returns (bool) {
return isApprovedForAll(owner(), user);
}
function getMyToken(address to, uint256 id) public {
transfer(owner(), to, id, 1, 'test');
}
}

Token information does not show when compiled

I am using the code below to create a smart contract, which receives BNB and sends the token created by the contract back.
I'm using Remix, and selecting the DEX contract to compile.
However, when I do this, the Token information does not appear on BscScan.
Example: https://testnet.bscscan.com/token/0xb570E6Fff85CBE695c9394bDa7d55fb38a009A28
And I can't add it to my wallet either, it says that the token code doesn't recognize it.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.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 ERC20Basic is IERC20{
string public constant name = "ByeSeel";
string public constant symbol = "BYS";
uint8 public constant decimals = 18;
//event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
//event Transfer(address indexed from, address indexed to, uint tokens);
mapping(address => uint256) balances;
mapping(address => mapping (address => uint256)) allowed;
uint256 totalSupply_ = 10000000 * 10 ** 18;
using SafeMath for uint256;
constructor() {
balances[msg.sender] = totalSupply_;
}
function totalSupply() public override view returns (uint256) {
return totalSupply_;
}
function balanceOf(address tokenOwner) public override view returns (uint256) {
return balances[tokenOwner];
}
function transfer(address receiver, uint256 numTokens) public override returns (bool) {
require(numTokens <= balances[msg.sender]);
balances[msg.sender] = balances[msg.sender].sub(numTokens);
balances[receiver] = balances[receiver].add(numTokens);
emit Transfer(msg.sender, receiver, numTokens);
return true;
}
function approve(address delegate, uint256 numTokens) public override returns (bool) {
allowed[msg.sender][delegate] = numTokens;
emit Approval(msg.sender, delegate, numTokens);
return true;
}
function allowance(address owner, address delegate) public override view returns (uint) {
return allowed[owner][delegate];
}
function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
require(numTokens <= balances[owner]);
require(numTokens <= allowed[owner][msg.sender]);
balances[owner] = balances[owner].sub(numTokens);
allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
balances[buyer] = balances[buyer].add(numTokens);
emit Transfer(owner, buyer, numTokens);
return true;
}
event Received(address, uint);
receive() external payable {
emit Received(msg.sender, msg.value);
}
}
library SafeMath {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
} }
contract DEX {
event Bought(uint256 amount);
event Sold(uint256 amount);
IERC20 public token;
constructor() {
token = new ERC20Basic();
}
function buy() payable public {
uint256 amountTobuy = msg.value;
uint256 dexBalance = token.balanceOf(address(this));
require(amountTobuy > 0, "You need to send some Ether");
require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
token.transfer(msg.sender, amountTobuy);
emit Bought(amountTobuy);
}
function sell(uint256 amount) public {
require(amount > 0, "You need to sell at least some tokens");
uint256 allowance = token.allowance(msg.sender, address(this));
require(allowance >= amount, "Check the token allowance");
token.transferFrom(msg.sender, address(this), amount);
payable(msg.sender).transfer(amount);
emit Sold(amount);
}
receive() external payable {
buy();
}
}
The problem is that the DEX contract was not extending to the ERC20Basic contract
So I had to do:
contract DEX is ERC20Basic
This solved it, but I still have problems with the purchase and sale contract.

Can't use fallback. Nothing happen! function() external payable {}

pragma solidity >=0.5.1 <0.6.0;
contract HelloWorld {
mapping(address => uint) public balance;
uint public countOfInvestors = 0;
mapping(address => uint) public time;
event Invest(address investor, uint256 amount);
function deposit() private {
if (msg.value > 0) {
if (balance[msg.sender] == 0) {
countOfInvestors += 1;
}
balance[msg.sender] = msg.value;
time[msg.sender] = now;
emit Invest(msg.sender, msg.value);
}
}
function() external payable {
deposit();
}
}
When i SEND SOME TRX ON CONTRACT i have no new data on tronscan, contract balance increased but not display any transaction
How to make contract should what i need?
No one events and transactions but i sent few times
Only a maximum of 2300 gas can be used on a fallback function, and your deposit function 100% uses more than that.
Since you used too much gas, the fallback function won’t get called.
https://ethereum.stackexchange.com/questions/5992/how-much-computation-can-be-done-in-a-fallback-function