How to send ETH to smart contract? - solidity

I want an address to send ETH to the smart contract in the RSVP function.
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract MeetingCreation {
struct Meeting {
address meeting_creator;
uint256 meetingID;
string name;
string description;
uint256 start_date;
uint256 end_date;
uint256 max_tickets;
uint256 ticket_price;
uint256 current_tickets_sold;
address[] attendees;
}
function sendETHtoContract(uint256 j) public payable {
}
function RSVP (uint256 MEETINGID) public payable {
//get the Meeting ID
Meeting storage m = meetings[MEETINGID];
require(m.current_tickets_sold < m.max_tickets,
"No more tickets available"
);
require(msg.sender.balance >= m.ticket_price,
"Not enough funds"
);
console.log("funds before paying", msg.sender.balance);
console.log("funds in smart contract before paying", address(this).balance);
//Attempt #1 To send ETH to contract
sendETHtoContract(m.ticket_price);
//Attempt #2 To send ETH to contract
(bool success, ) = address(this).call{value: m.ticket_price}("");
//Attempt #3 to send ETH to contract
payable(address(this).transfer(msg.value));
console.log("funds AFTEr paying", msg.sender.balance);
console.log("funds in smart contract AFTER paying", address(this).balance);
address[] storage adr;
adr = m.attendees;
adr.push(msg.sender);
m.current_tickets_sold += 1;
}
Both sendETHtoContract and (bool, success) result in not sending any ETH when I tried 3 different addresses.
funds before paying 9999949127225257315696
funds in smart contract before paying 0
funds AFTEr paying 9999949127225257315696
funds in smart contract AFTER paying 0
funds before paying 9999955000801324655336
funds in smart contract before paying 0
funds AFTEr paying 9999955000801324655336
funds in smart contract AFTER paying 0
When I tried using the transfer function, this is the error I get when the contract tries to compile:
"send" and "transfer" are only available for objects of type "address payable", not "address".

I assume that you can delete your attempt for the simple reason that when you add payable modifier, it handle the transfer about ETH from address to smart contract and viceversa.
Said this, I think that you're not enhancing msg.value field. If you using remix IDE, before call RSVP function go into DEPLOY & RUN TRANSACTIONS section and put into VALUE textbox a value that you want sending to smart contract and then you can call RSVP function.
I adjust your smart contract delete your attempts. Try it:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract MeetingCreation {
struct Meeting {
address meeting_creator;
uint256 meetingID;
string name;
string description;
uint256 start_date;
uint256 end_date;
uint256 max_tickets;
uint256 ticket_price;
uint256 current_tickets_sold;
address[] attendees;
}
mapping(uint => Meeting) meetings;
function RSVP (uint256 MEETINGID) public payable {
//get the Meeting ID
Meeting storage m = meetings[MEETINGID];
require(m.current_tickets_sold < m.max_tickets,
"No more tickets available"
);
require(msg.sender.balance >= m.ticket_price,
"Not enough funds"
);
address[] storage adr;
adr = m.attendees;
adr.push(msg.sender);
m.current_tickets_sold += 1;
}
// NOTE: Get smart contract balance
function getSmartContractBalance() external view returns(uint) {
return address(this).balance;
}
}

Related

What is missing from this Smart Contract?

I am working on a smart contract, and my goal is that when a certain (variable) amount of eth gets send to the contract, it gets split and payed to three adresses. I currently have this code. Am I missing something? It doesn't work in Remix unfortunately. Thanks in advance for your valuable time!
`pragma solidity ^0.6.0;
contract PaymentSplitter {
address payable addressOne;
address payable addressTwo;
address payable addressThree;
uint256 amount;
constructor(address payable _addressOne = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2, address payable _addressTwo = 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db, address payable _addressThree = 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB) public {
addressOne = _addressOne;
addressTwo = _addressTwo;
addressThree = _addressThree;
}
function splitPayment(uint256 _amount) public {
amount = _amount;
addressOne.transfer(_amount / 3);
addressTwo.transfer(_amount / 3);
addressThree.transfer(_amount / 3);
}
function getSplitAmount() public view returns (uint256) {
return amount;
}
// This will be invoked when the contract receives a payment
function() external payable {
splitPayment(msg.value);
}
}`
We tried various smart contract, but without any significant results
I modified your smart contract. I put some notes, to understand you some errors in your logic:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract PaymentSplitter {
address payable addressOne;
address payable addressTwo;
address payable addressThree;
uint256 amount;
constructor(address _addressOne, address _addressTwo, address _addressThree) public {
addressOne = payable(_addressOne);
addressTwo = payable(_addressTwo);
addressThree = payable(_addressThree);
}
// NOTE: Avoid passing parameter with value because with this statement 'address(this).balance' I receive the entire amount of Ether stored in smart contract
function splitPayment() public {
// NOTE: I retrieve entire amount stored in smart contract balance after send value to it
uint smartContractBalance = address(this).balance;
// NOTE: Since smart contract balance should be divided into three equal part the amount, I make this operation one time and put the value inside 'amount' variable. Then
// I transfer the equal amount to three accounts.
amount = smartContractBalance / 3;
addressOne.transfer(amount);
addressTwo.transfer(amount);
addressThree.transfer(amount);
}
function getSplitAmount() public view returns (uint256) {
return amount;
}
// This will be invoked when the contract receives a payment
receive() external payable {
splitPayment();
}
}
NOTE: Consider to use address.call{value}() for send amount from smart contract to accounts.
Is this a better contract? A few changes, and different amounts have to be sent to different addresses.
pragma solidity ^0.8.17;
contract Blockbook{
address payable public address1;
address payable public address2;
address payable public address3;
constructor(address payable _address1, address payable _address2, address payable _address3) public {
address1 = _address1;
address2 = _address2;
address3 = _address3;
}
function splitPayment(uint amount) public payable {
address1.transfer(amount * 0.8);
address2.transfer(amount * 0.1);
address3.transfer(amount * 0.1);
}
receive() external payable {
splitPayment(msg.value);
}
function updateAddresses(address payable _address1, address payable _address2, address payable _address3) public {
address1 = _address1;
address2 = _address2;
address3 = _address3;
}
}

Problem sending eth from contract to contract

pragma solidity ^0.8.7;
// SPDX-License-Identifier: MIT
contract Client {
address payable private hub;
address payable public owner;
uint256 public balance;
constructor(address payable _hub) {
hub = _hub;
owner = payable(msg.sender);
}
receive() payable external {
balance += msg.value;
}
function withdraw(address payable destAddr) public {
require(msg.sender == owner, "Only owner can withdraw funds");
uint amount = address(this).balance;
destAddr.transfer(amount);
}
function start() public payable {
require(msg.sender == owner, "Only owner can start the process");
uint amount = address(this).balance;
hub.transfer(amount);
balance = 0;
}
function setHub(address payable _new) public {
require(msg.sender == owner, "Only owner can change address");
hub = _new;
}
}
Hi i have a problem, when I deploy this contract and put as input (hub) the other contract, then send eth to this contract, i call the "start" function and throw a gas estimation error.
Someone who can help me pls...
I'm expecting that calling the start function fund will be sent to the other contract that also have a function for receiving eth
receive() payable external {
balance += msg.value;
}
You are getting that gas estimation error because your receive function on the second contract is not empty and the transaction does not have enough gas to execute the code. transfer only sends the amount of gas necessary to execute a transfer of ether (21,000 gas) and nothing more.
You can use call instead of transfer to send ether and set the amount of gas that you want to send. transfer is actually no longer recommended for sending ether.

Sending ERC20 tokens using the transfer function

I'm pretty new to programing in solidity and I'm currently trying to run a simple smart contract in Remix, seen bellow:
pragma solidity ^0.8.0;
import "github.com/OpenZeppelin/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
contract Swap {
address public owner;
uint256 public balance;
event TransferReceived(address _from, uint _amount);
event TransferSent(address _from, address _destAddr, uint _amount);
constructor() {
owner = msg.sender;
}
receive() payable external {
balance += msg.value;
emit TransferReceived(msg.sender, msg.value);
}
function withdraw(uint amount, address payable destAddr) public {
require(msg.sender == owner, "Only owner can withdraw funds");
require(amount <= balance, "Insufficient funds");
destAddr.transfer(amount);
balance -= amount;
emit TransferSent(msg.sender, destAddr, amount);
}
function transferERC20(IERC20 token, address to, uint256 amount) public {
require(msg.sender == owner, "Only owner can withdraw funds");
uint256 erc20balance = token.balanceOf(address(this));
require(amount <= erc20balance, "balance is low");
token.transfer(to, amount);
emit TransferSent(msg.sender, to, amount);
}
}
While I can successfully send BNB and call the withdraw function giving the value sent and my wallet address in the BSC testnet, I'm having issues when running the transferERC20 function. The only output that I get when calling this method is the following message:
Gas estimation errored with the following message (see below). The
transaction execution will likely fail. Do you want to force sending?
Internal JSON-RPC error. { "code": -32000, "message": "execution
reverted" }
I've tried several different addresses that I found in the testnet.bscscan website for BNB while making sure that the contract had enough funds for transfering, but I had no success.
Can someone suggest what might be going wrong in my contract/setup? Am I making this transfer properly?
fix constrcutor
constructor() {
// payable allows payment of ether with a call.
owner = payable(msg.sender);
}
make sure those require statements are satisfied
require(msg.sender == owner, "Only owner can withdraw funds");
require(amount <= balance, "Insufficient funds");
check that you are connected to correct network

How to send ETH directly from ERC721 (OpenZeppelin) contract to the PaymentSplitter contract?

I have an openZeppelin ERC721 NFT contract (MyNFTPrice.sol) and also a separate PaymentSplitter contract. My understanding is that these two contract need to be deployed separately. My question is, how do I send the price of minting from my NFT contract (MyNFTPrice.sol) to the PaymentSplitter contract? Currently, the price for minting an NFT resides in the MyNFTPrice.sol contract address.
MyNFTPrice.sol
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract MyNFTPrice is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() public ERC721("MyNFTPrice", "NFTPRICE") {}
// Mint new NFT
function mintNFT(address recipient, string memory tokenURI) public payable {
require(msg.value >= 50000000000000000, "You need 0.05 ETH to mint the NFT");
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(recipient, newItemId);
_setTokenURI(newItemId, tokenURI);
}
}
You can use the transfer() member of the address payable.
function mintNFT(address recipient, string memory tokenURI) public payable {
require(msg.value >= 50000000000000000, "You need 0.05 ETH to mint the NFT");
// effectively redirects the `msg.value` to the `0x123` address
payable(address(0x123)).transfer(msg.value);
// ... rest of your code
}
Replace the 0x123 to the real address of the PaymentSplitter.
You can also store the address in a variable and change it when you need to. In this case, it's recommended to use an authorization mechanism, such as the Ownable pattern, so that only an authorized sender can change the value.
Since the PaymentSplitter is a contract, it needs to contain the receive() or fallback() payable function. Otherwise the PaymentSplitter as the receiver would reject the incoming payment and effectively cause the whole mintNFT() transaction to revert.
contract PaymentSplitter {
receive() external payable {
// can be empty
}
}

Transaction Reverted even though I have a payable fallback function to receive eth, when I deploy without sending eth it works

Here is my code:
pragma solidity 0.8.6;
import "./Allowance.sol";
contract SharedWallet is Allowance {
event MoneySent(address indexed _beneficiary, uint _amount);
event MoneyReceived(address indexed _from, uint _amount);
function withdrawMoney(address payable _to, uint _amount) public ownerOrAllowed(_amount) {
require(_amount <= address(this).balance, "Contract doesn't own enough money");
if(!isOwner()) {
reduceAllowance(msg.sender, _amount);
}
emit MoneySent(_to, _amount);
_to.transfer(_amount);
}
function renounceOwnership() public override onlyOwner {
revert("can't renounceOwnership here"); //not possible with this smart contract
}
fallback () external payable {
emit MoneyReceived(msg.sender, msg.value);
}
}
Are you trying to send Ether to the contract as you deploy it? As I do not think you can do that easily. Well, there is a hacky way. Ethereum contract address is deterministic, i.e. knowing the creator's address and their nonce you can calculate the future address of your smart contract. And then send ETH to that address prior to deploying the contract.