Sending ether in solidity smart contract - solidity

I'm writing a smart contract in solidity, and I need to send ether from my coinbase (eth.coinbase) to my friend coinbase (address = 0x0123).
If I try to use an address.send(value) the function doesn't decrease my account and doesn't increase my friend coin base.
I only can send ether in geth with "eth.sendTransaction(VALUE, {from:eth.coinbase, to:address})"
so I want to know if its possible to call an eth method in contract or a different way to send ether in smart contract
function withdraw() returns (bool) {
address x = 0x0123;
uint amount = 100 ether;
if (x.send(amount))
return true;
else
return false;
}

address.send does not propagate exception that's why you don't see any issue. Make sure you have enough Eth in your contract.
Have a look on this documentation that will explain how to set up your smart contract: https://developer.ibm.com/clouddataservices/2016/05/19/block-chain-technology-smart-contracts-and-ethereum/

You can use following function. just change variable name with yours.
function Transfer(uint amount,address reciever){
// check sender balance is less than of amount which he wants to send.
if(balance[msg.sender] < amount){
return;
}
// decrease sender's balance.
balance[msg.sender] = balance[msg.sender] - amount;
// increase reciever's balance.
balance[reciever] = balance[reciever] + amount;
// event
// transaction(msg.sender,reciever,amount);
}

Related

Reentrancy attack with withdraw amount

I've been working on different ways to perform reentrancy attacks and there is one case which I have still not seen any working example on the internet. In the book Mastering Ethereum, the reentrancy attack is explained with a contract where the function withdraw(uint amount) takes the input amount. The version on Solidity has been updated a lot since then and whenever I try to perform a similar attack, it does not work. It works whenever the function withdraw() takes no arguments and it also works when using older versions.
Could anyone provide an example of a reentrancy attack where the target contract takes the withdraw amount as input?
Thank you!
Let's say you have 1 ether in the contract, and the contract has a total of 10 ether. You're trying to steal all 10 ether with re-entrancy, but that necessarily means the variable tracking your balance must underflow to the equivalent of uint256(-9) ether -- you're trying to withdraw 1 ether 10 times.. This will cause a revert in Solidity 0.8.0 or higher, since it has built in under/overflow protection. If you want it to work in 0.8.0, you have to wrap the balance reduction line with unchecked.
This code is still vulnerable to re-entrancy in 0.8.0, but only because it sets the balance to zero, and can't underflow
mapping(address => uint256) public balance;
function deposit() external payable {
balance[msg.sender] += msg.value;
}
function withdraw() external {
msg.sender.call{value: balance[msg.sender]}(""); // re-entrancy
balance[msg.sender] == 0; // cannot underflow
}
function withdrawV2(uint256 value) external {
require(value <= balance[msg.sender], "you don't have that much"); // not that this does anything...
msg.sender.call{value: balance[msg.sender]}("");
unchecked { // now it can underflow
balance[msg.sender] -= value;
}
}

I need help to customize my smart contract lottery project

Things that I need to add as functions:
I want to integrate a management fee of 1% of the total pot. Execution: The management fee (going to contract owner) will be deducted to the total prize before the remaining 99% amount will be sent to the lottery winner. I need to add it to the selectWinner function.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Lottery{
address public manager;
//global dynamic array for participants.
address payable[] public participants;
constructor()
{
//msg.sender is a global variable used to store contract address to manager.
manager=msg.sender;
}
//receive function only creates once in a smart comtract.
//this function help to transfer the ether.
//always use with external keyword and payable.
receive() external payable{
//require is used as a if statement. it check if ether value is 2 then only run below code.
require(msg.value==0.02 ether);
participants.push(payable(msg.sender));
}
function getBalance() public view returns(uint){
//only manager check the total balance.
require(msg.sender==manager);
return address(this).balance;
}
//this random function will genrate random value and from participant array and then return to the winnerFunction.
function random() public view returns(uint)
{
return uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp, participants.length)));
}
//this function decide the winner randomly.
function selectWinner() public{
require(msg.sender==manager);
require(participants.length>=3);
uint r=random(); //call random function.
uint index=r % participants.length; //for making random function value in array length range.
address payable winner;
winner=participants[index];
winner.transfer(getBalance());
participants=new address payable[](0);
}
}
I need help to do it. Thank you.
I think something like this should work. I don't have time to test the function right now, but will edit this answer later today. Hope it helps you at the moment.
function selectWinner() public {
require(msg.sender==manager);
require(participants.length>=3);
uint r=random(); //call random function.
uint index=r % participants.length; //for making random function value in array length range.
address payable winner;
winner=participants[index];
uint balance = getBalance(); // balance is in wei
uint fee = balance * 0.01 ether; // 1% in wei
uint amountToTransfer = balance - fee;
winner.transfer(amountToTransfer);
_withdrawFee(fee); // transfer fee to manager
participants=new address payable[](0);
}
function _withdrawFee(uint feeAmount) payable private {
msg.sender.transfer(feeAmount);
}

Ethereum lottery smart contract reverts due to insufficient funds. Where does my code consumes that much gas?

I am experimenting with solidity and I faced an issue for what I could not find a solution.
The program should let addresses buy ticket at a preset price, and the owner can start the "roll the dice" function which randomly selects the winner and transfer the funds to that address.
I beleive that this program would be easier with mapping instead of array, but getting experience with array was the main purpose of this program.
The error happens when the user calls buyTicket function. Based on the response I beleive the contract comsumes too much gas. Can someone tell me why it doesnt work? I appreciate any other helping comment regarding the rest of the code:)
Thanks in advance!
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract Lottery {
constructor () {
owner = msg.sender;
}
address[] public Players;
address private owner;
uint public ticketPrice;
uint public price;
uint public nonce;
uint public variations;
address payable winner;
bool hasTicketAnswer;
event Winner(address _winner);
event PriceSet(uint _setPrice);
event TicketBought();
function setTicketPrice(uint _ticketPrice) public {
require(msg.sender == owner, "Only Owner...");
ticketPrice = _ticketPrice;
emit PriceSet(_ticketPrice);
}
function hasTicket(address _sender) private returns(bool) {
hasTicketAnswer = false;
for (uint i = 0; i < Players.length; i++) {
if (Players[i] == _sender) hasTicketAnswer = true;
}
return hasTicketAnswer;
}
function buyTicket() external payable {
require(ticketPrice > 0, "Price did not set, be patient...");
require(hasTicket(msg.sender) == false, "You cannot have two tickets...");
require(msg.sender.balance <= ticketPrice, "Insufficient funds...");
payable(address(this)).transfer(ticketPrice);
Players.push(address(msg.sender));
price += msg.value;
emit TicketBought();
}
function checkBalance() public view returns(uint) {
return address(this).balance;
}
function rollTheDice() public payable {
variations = Players.length;
winner = payable(Players[uint(keccak256(abi.encodePacked(msg.sender, nonce, block.timestamp))) % variations]);
winner.transfer(price);
emit Winner(winner);
}
receive () external payable {
}
}
Besides probably finding the problem, I've read some things that I'd like to comment on.
Your problem
The reason why you're getting the "Insufficient funds" error is because the condition is returning false. You're asking the msg.sender balance to be less than or equal (<=) to ticketPrice, when it should be more than or equal (>=).
Let's say Alice has a balance of 0.05 ETH and interacts with the contract whose ticket price is 0.001 ETH...
require(0.05 ETH <= 0.001 ETH) // Reverting...
Observations
I'm curious if you're intentionally coding the buyTicket function in that way. What it actually does is checking if the msg.sender has enough ETH to buy a ticket in its wallet, which doesn't mean that the user is effectively sending ETH in the transaction (the amount of wei sent in the transaction can be checked with msg.value, you can read more about it here).
My last observation is the payable(address(this)).transfer(ticketPrice) line of code, because it's not necessary to do so, once a payable function receives ETH, it is saved into the contract... In that line you're just making the Bob's contract to send ETH to the Bob's contract, which just wastes gas without reason
I hope I've helped with you and if I wasn't completely clear in any thing I've said don't doubt in asking me

How can I transfer eth from an account wallet to a smart contract

I'm creating a smart contract that allows people to pay for a monthly subscription
I got stacked in this :
how to transfer plan.amount from the user wallet to the smart contract?
function subscribe(uint planId) external {
Plan storage plan = plans[planId];
require(plan.merchant != address(0), 'address not valid');
bool sent = payable(address(this)).send(plan.amount);
require(sent, "tx failed");
emit PaymentSent(
msg.sender,
plan.merchant,
plan.amount, // the monthly amount for Subscription
planId,
block.timestamp
);
subscriptions[msg.sender][planId] = Subscription(
msg.sender,
block.timestamp,
block.timestamp + 4 weeks // next payement
);
emit SubscriptionCreated(msg.sender, planId, block.timestamp);
}
The subscribe() function needs to use the payable modifier in order to accept ETH. Then you can validate how much the user has sent while invoking your function with the msg.value global variable.
It's not possible to request a specific amount from the contract, as the contract code is executed after the user has sent the transaction. You always need to validate how much has the user sent along with the transaction invoking the function.
function subscribe(uint planId) external payable {
// revert if the sent value is not expected
require(msg.value == 1 ether, "You need to send 1 ETH");
}
However you can control the predefined value on the UI, while creating the transaction request to their MetaMask or other wallet.
await window.ethereum.request(
method: 'eth_sendTransaction',
[
from: userAddress,
to: yourContract,
data: <invoking the subscribe() function>,
value: <1 ETH in wei, in hex>
]
);
Docs: https://docs.metamask.io/guide/ethereum-provider.html#ethereum-request-args

Token balance check is not working in Solidity smart contract

here is my code snippet and i have no idea why its not working
function Testdeposit(address _assetAddress) public returns (uint256 status)
{
//IERC20 erc20 = IERC20(_assetAddress);
//erc20.transferFrom(senderAddress, address(this), _amount));
//uint256 amount = erc20.allowance(senderAddress, address(this));
uint256 amount = IERC20(_assetAddress).balanceOf(address(this));
return amount;
}
i am using a standard IERC20 interface. just it dsnt have an event to emit. i assume it to return me 0 if there is no balance but its gvng me erro. Transcation not going through.
Any suggestions??
It is not working because you may have not overridden the IERC20 functions. At least as they should. I would highly recommend using the ERC20 standard instead, just for how easy it is to implement.