Refund all addresses entered on solidity contract - blockchain

I have a problem related to refund the users entered inside the solidity contract. I don't, have any idea if is possible iterate all the players of my contract and refund all of them with all the balance.I read in some tutorials, iterate inside the solidity contract cost a lot of gas depends of the numer of iterations.
contract Lottery{
address payable public manager;
string public name; // short name (up to 32 bytes)
address [] players;
uint256 nTickets;
address winner;
bool enable;
uint256 minimunContribution;
mapping(address => uint) public balances;
constructor (string memory LotteryName, uint minimun, address payable creator) public {
manager = creator;
name = LotteryName;
winner = address(0);
enable = true;
minimunContribution = minimun;
}
modifier restricted() {
require(msg.sender == manager, "Access forbidden");
_;
}
function enterInToLottery() public payable {
require(msg.value > minimunContribution && enable == true, "Insufficient funds to allow transfer");
players.push(msg.sender);
balances[msg.sender] += msg.value;
nTickets++;
}
//this function refund
function paybackEther(bool newfinished) public restricted {
enable = !newfinished;
selfdestruct(msg.sender);
}}
Thanks in advance to all.

Yes that can be problematic as it will use a lot of gas and may even hit limits. To solve this it is better to allow the users to withdraw the balance themselves, so they pay for the gas. Or in fact you can allow anybody to make that call. So you can offer a call refund(account:uint256) which transfers the balance (if any) to given account. Note that this would not be using msg.sender, so that anybody (including the admin) can do this transfer.
Keep in mind they need to know that they have a balance, so make sure you're emitting an event or similar. Also provide a balanceOf(address) call so they can check.
Hope this makes sense & works for you.

Related

Is payble keyword neccessary even if I am not taking any ether/matic?

function sendGift(uint256 _mintAmount,address recipient) public payable {
uint256 supply = totalSupply();
require(!paused);
require(_mintAmount > 0);
require(_mintAmount <= maxMintAmount);
require(supply + _mintAmount<= availableSupplyForSale);
//require(_amount >= cost * _mintAmount);
require(coinToken.allowance(msg.sender,address(this))>=cost * _mintAmount);
coinToken.transferFrom(msg.sender, address(this),cost * _mintAmount);
if(supply<currentSupply){
for (uint256 i = 1; i <= _mintAmount; i++) {
_safeMint(recipient, supply + i);
}
}
else{
uint256[] memory tokenIds = walletOfOwner(address(this));
for(uint256 i=1;i<=_mintAmount;i++)
transferFrom(address(this),recipient,tokenIds[i]);
}
}
Do I need to use payable here? Contract does not take any matic. It only takes custom token as payment .
(bool os, ) = payable(admin).call{value: address(this).balance}("");
require(os);
Also since I am not taking any matic, will this above line necessary for withdraw assets from contract as an owner? I have a sense that this above line only is useful to withdraw eth/polygon.
I am a new blockchain kid. Please help.
The payable modifier of a function is required when your function accepts native tokens (ETH, BNB, MATIC, ... depending on the network).
So in this case, you can safely remove it from the function header.
// removed `payable`
function sendGift(uint256 _mintAmount,address recipient) public {
The low-level .call() also doesn't require using payable to send native tokens.
payable(admin).call{value: address(this).balance}("");
However, if you used the high-level .transfer(), then you'd need to cast the admin variable type address to its extension type address payable using the typecasting function.
// will not work as it's type `address`
admin.transfer(address(this).balance);
// need to cast type `address` to type `address payable`
payable(admin).transfer(address(this).balance);
In order to withdraw tokens from your contract address, you need to invoke the transfer() function (defined in the ERC-20 standard) on the token contract. Do not confuse it with the native transfer() function of address payable, these are two separate things, just with the same name.
interface IERC20 {
function transfer(address, uint256) external returns (bool);
}
contract MyContract {
function withdrawToken() {
IERC20(tokenContractAddress).transfer(recipient, amount);
}
}

How to use transfer function in solidity

I created smart contract to transfer ETH from one account to another, ETH deduction occurs but send to other address(which is not specified). Please help me to resolve this problem.
//SPDX-License-Identifier:MIT
pragma solidity ^0.8.12;
contract ETH{
address public buyer;
uint public amt;
address public seller;
constructor(){
seller = msg.sender;
}
function add(address payable _buyer) payable public{
buyer = _buyer;
payable(buyer).transfer(amt);
}
function bal() view public returns(uint){
return buyer.balance;
}
function s() payable public returns(uint){
return msg.value;
}
}
The default value of amt is 0 and your code does not set this property (to a non-zero value) anywhere.
Which effectively makes your .transfer(amt) function to send 0 ETH to the buyer and keep all the ETH, that you sent along with the transaction, in the contract.
If you want to redirect the sent amount, there's the msg.value global variable, which reflects the current value sent with the transaction.
payable(buyer).transfer(msg.value);

Solidity: Disable Buying and Selling if CurrentPrice is below LastTransactionPrice?

Is it possible in Solidity to compare
LastTransactionPrice with CurrentAsk & CurrentBid?
then
Disable Buying/Selling if the price (Ask/Bid) is below LastTransactionPrice?
Thank you!
You create 3 state variables for CurrentAsk, CurrentBid and LastTransactionPrice:
uint256 CurrentAsk private;
uint256 CurrentBid private;
uint256 LastTransactionPrice private;
then write to setters to mutate those two state variables:
// askPrice gets set by the seller
function setCurrentAsk(uint256 askPrice) public {
CurrentAsk=askPrice
}
// bidPrice gets set by the buyer
function setCurrentBid(uint256 bidPrice) public {
CurrentBid=bidPrice
}
You can write a require statement to add buying/selling function but in this way, people still can call setCurrentAsk and setCurrentBid functions and pay gas fees. To be more efficient, you add require statements to both functions.
function setCurrentAsk(uint256 askPrice) public {
require(askPrice>LastTransactionPrice,"ask higher amount")
CurrentAsk=askPrice
}
function setCurrentBid(uint256 bidPrice) public {
require(bidPrice > LastTransactionPrice, "ask higher amount")
CurrentBid=bidPrice
}
require statement will check the current condition and if does not return true, it will revert the function execution and solidity will show the error that you defined: "ask higher amount"

Does it make sense to manage balance manually inside smartcontract?

I am using Solidity to deploy smartcontract to a test Ethereum network launched by Ganache. I read some demo code of contract and one of them looks like:
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.4;
pragma experimental ABIEncoderV2;
contract Ledger {
struct TransferRequest {
string title;
uint256 amount;
string bsb;
string accountName;
string accountNumber;
}
mapping(address => uint256) balances;
address payable owner;
event Transfered(bool _success, address _from, address _to, uint256 amount);
constructor() payable {
owner = payable(msg.sender);
balances[tx.origin] = 10000;
}
function sendCoin(address payable receiver, uint256 amount)
payable public
{
require(msg.sender == owner);
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Transfered(true, msg.sender, receiver, amount);
}
function getBalance(address addr) public view returns (uint256) {
return balances[addr];
}
}
As you can see above that the contract manages the balance by itself rather than using the balance from the blockchain. There is no real ether transfer inside sendCoin method. Does this mean there is no real transaction in the blockchain. Then what the point of building a contract like that. What would be the relationship between balance managed by blockchain and balance managed by contract?
the contract manages the balance by itself rather than using the balance from the blockchain
Each state change (in this case change of balances storage property value) is recorded on the blockchain. So the contract is reading the balance from the blockchain.
However, the way Ethereum network is designed, an address can only have few properties - its bytecode (non-zero bytecode means it's a smart contract), its balance, and few others. Since there's only one property for balance (and not a list of balances), it's used for the native ETH balance. Any token balances are stored in the contracts of the respective tokens.
You can read more about the token balance storage design in the final version of ERC-20 and the linked documents. This is the first standard that introduced tokens on Ethereum.

Where would a transaction take place in my Smart Contract

I am making a simple smart contract that is essentially a ledger that people can sign with a string (UI to come) and then pass onto a next person (using their ether address). I just wanted to create something that could be passed from person to person while recording its journey.
The logic of 'transferring' the signing-ledger is all done within the smart contract, with it existing as a mapping and the key value of an address changing from 0 to 1 signifying ownership (1 person owning it at a time). Because there's no actual transfer of ether/actual monetary value, where would actual ethereum transactions be occurring in this contract?
Also to sign the ledger I verify that the public key signing it has 1 as its value in the mapping, but how would I check that that person owns that public key (using a private key)?
my solidity code so far:
pragma solidity ^0.4.4;
contract Pass{
mapping(address => bool) ownership;
mapping(address => string) notes;
constructor(address genesis) public {
ownership[genesis] = true; //this address starts with it
}
function checkOwnership(address p) public view returns(bool){
if(ownership[p]){
return true;
}
return false;
}
function sign(string signedNote) public returns(uint){ // 1 on success 0 on fail
if(checkOwnership(msg.sender)){ //if msg.sender owns the note
notes[msg.sender] = signedNote;
return 1;
}
return 0;
}
function pass(address recipient) public returns(uint){ // 1 on success 0 on fail
if(checkOwnership(msg.sender)){ //if msg.sender owns the note
ownership[msg.sender] = 0;
ownership[recipient] = 1;
return 1;
}
return 0;
}
function viewNotes(address participant) public returns(string){ // signed note on success nothing on fail
if(notes[participant] !== 0){
return (notes(participant));
}
}
}
The logic of 'transferring' the signing-ledger is all done within the smart contract, with it existing as a mapping and the key value of an address changing from 0 to 1 signifying ownership (1 person owning it at a time)
This is a common pattern known as the owner pattern. You can simplify this by simply keeping track of a single owner address and updating that, instead of using a mapping, since you only care about the current owner. Something as simple as:
address public owner;
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
constructor() {
owner = msg.sender;
}
function transferOwnership(address _owner) onlyOwner {
owner = _owner;
}
Open Zeppelin has a more complete implementation of ownership here.
Because there's no actual transfer of ether/actual monetary value, where would actual ethereum transactions be occurring in this contract?
Transactions do not require ether movement. You can call any public/external function on your contract with a 0 value transaction, and pass data to it. The transaction will execute on the blockchain like any other, and run the code you invoke within the contract.
Also to sign the ledger I verify that the public key signing it has 1 as its value in the mapping, but how would I check that that person owns that public key (using a private key)?
You are already checking is msg.sender matches the whitelisted address. For basic transactions, this means that the transaction has been signed by the address in msg.sender (msg.sender can also be a contract, if another contract calls yours. To check who actually signed the transaction in all scenarios, you must use tx.origin).