I try to get a loop run through all structs associated with the caller address, but I can't get my head around this warning. I think I understand the problem, but can't get my head around what should I do differently to achieve this result the other way.
The error I am getting:
TypeError: Integer constant expected.
--> minitest.sol:30:31:
|
30 | balance += Wallet[walletNumbers[msg.sender][i]].balance;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
My code simplified just for the error part:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^ 0.8 .0;
contract MiniTest {
uint nextWalletNumber = 0;
struct Wallet {
address owner;
uint balance;
uint debt;
}
Wallet[] public walletInfo;
mapping(address => uint[]) public walletNumbers;
function createWallet() public {
Wallet memory newWallet = Wallet(msg.sender, 1000, 0);
walletInfo.push(newWallet);
walletNumbers[msg.sender].push(nextWalletNumber);
nextWalletNumber++;
}
function allWalletsBalance() public view returns(uint) {
uint balance;
for (uint i; i < walletNumbers[msg.sender].length; i++) {
balance += Wallet[walletNumbers[msg.sender][i]].balance;
}
return balance;
}
}
Is there another way to achieve this for loop and take out uint from all structs associated with that address?
although I could not figure out the relationship between your state variables, this line of code is
balance += Wallet[walletNumbers[msg.sender][i]].balance;
Wallet is a struct. instead you should be using walletInfo the name of the array.
balance += walletInfo[walletNumbers[msg.sender][i]].balance;
Related
In this part of my smart contract, Remix is displaying an error:
function rebase() public {
for (address wallet in balances) {
uint256 reward = balances[wallet] * 0.002;
balances[wallet] += reward;
totalSupply -= reward;
}
}
The error is:
ParserError: Expected ';' but got reserved keyword 'in'
--> test.sol:70:25: | 70 | for (address wallet in balances) { | ^^
I also tried another method:
function rebase() public {
for (uint i = 0; i < balances.length; i++) {
bytes32 walletHash = balances[i];
address wallet = address(walletHash);
uint256 reward = balances[wallet] * 0.002;
balances[wallet] += reward;
totalSupply -= reward;
}
}
What could be the issue? I tried a lot been on this since yesterday,
I would be very happy if someone could assist me. What I'm trying to do is add the rebase function to the smart contract, where each wallet receives 0.2% / day based on the amount of tokens they have in their wallet.
function rebase() public {
for (uint i = 0; i < balances.length; i++) {
bytes32 walletHash = balances[i];
address wallet = address(walletHash);
uint256 reward = balances[wallet] * 0.002;
balances[wallet] += reward;
totalSupply -= reward;
}
}
for (address wallet in balances) {
This is a JavaScript syntax (and possibly some other languages use it too) but it's not valid syntax in Solidity.
for (uint i = 0; i < balances.length; i++) {
This is a valid Solidity syntax, assuming balances is an array.
If it's a mapping, then you cannot iterate through it, as the list of keys that have set values is unknown.
You might use the iterable mapping pattern. However, a common approach to rebase tokens is to update a multiplier - rather than update balance of each holder.
// how many % of the total supply each address owns
mapping(address => uint256) balancePercentages;
uint256 multiplier;
function rebase(uint256 _multiplier) external {
// the percentage of each holder stays the same
multiplier = _multiplier;
}
function balanceOf(address holder) external view returns (uint256) {
return balancePercentages * multiplier;
}
This my code ..if someone can help ..thanks in advance
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2 ;
contract Users {
struct Drug { // Vehicle = Drug
string name;
uint Qt;
uint Qs;
uint Qr;
}
event DrugAdded(
string name,
uint Qt,
uint Qs,
uint Qr
);
Drug[] public drugs;
uint counter=0;
function addDrug(string memory _name, uint _Qt, uint _Qs, uint _Qr) public {
drugs.push(
Drug(_name, _Qt,_Qs,_Qr)
);
emit DrugAdded(_name, _Qt,_Qs,_Qr);
counter++;
}
function getdrugs(string memory _name) public view returns (Drug[] memory) {
for(uint i=0;i<counter;i++){
if (keccak256(abi.encodePacked((drugs[i].name))) == keccak256(abi.encodePacked((_name)))){
return drugs[i];
}
}
}
}
i get error in last line:
TypeError: Return argument type struct Users.Drug storage ref is not implicitly convertible to expected type (type of first return variable) struct Users.Drug memory[] memory.
return drugs[i];
^------^
Because of how arrays are stored in memory, Solidity is not able to resize memory arrays. So when you're returning a dynamic-length array with an unknown length, you need to find out and declare its length first (see _getCount() in the example below) - and then fill each of its items.
You can find another example of a very similar thing in this answer.
function getdrugs(string memory _name) public view returns (Drug[] memory) {
Drug[] memory drugsToReturn = new Drug[](_getCount(_name));
uint256 index = 0;
for(uint i=0;i<counter;i++) {
if (keccak256(abi.encodePacked((drugs[i].name))) == keccak256(abi.encodePacked((_name)))){
drugsToReturn[index] = drugs[i];
index++;
}
}
return drugsToReturn;
}
function _getCount(string memory _name) private view returns (uint256) {
uint256 count = 0;
for(uint i=0;i<counter;i++) {
if (keccak256(abi.encodePacked((drugs[i].name))) == keccak256(abi.encodePacked((_name)))){
count++;
}
}
return count;
}
i'm new with solidity and i'm currently struggling iterating through a mapping index to get the values from a Struct
struct Stakes {
uint256 stakeDate;
uint256 stakeAmount;
}
mapping (address => Stakes[]) public addressToStaked;
function stake (uint256 _amount) public {
require(_amount > 0, "You must stake more than 0");
addressToStaked[msg.sender].push(Stakes(block.timestamp, _amount));
}
function returnStaked () public view returns (uint256[][] memory) {
uint256[][] memory result;
for (uint256 i = 0; i < 2; i++){
result[i] = [addressToStaked[msg.sender][i].stakeDate, addressToStaked[msg.sender][i].stakeAmount];
}
return result;
}
As shown on the code, i'm able to push the Struct Values into the mapping, but when i try to read the values as in the returnStaked function i get the error:
TypeError: Type uint256[2] memory is not implicitly convertible to expected type uint256[] memory.
I am not sure but i think you can't iterate through mapping to get values.. if you want to get the stake for the particular address .. below code will work..
function returnStaked (address addressStaked) public view returns (Stakes[] memory) {
return addressToStaked[addressStaked];
}
I will list some links for your references and if i found the way to do it.. i will update here...
https://solidity-by-example.org/app/iterable-mapping/
https://ethereum.stackexchange.com/questions/15337/can-we-get-all-elements-stored-in-a-mapping-in-the-contract
https://programtheblockchain.com/posts/2018/03/09/understanding-ethereum-smart-contract-storage/
I want to return an array of structs because i want to output all my data.
//SPDX-License-Identifier:MIT
pragma solidity ^0.8.0;
contract MyContract
{
mapping(uint256 => People) dataList;
uint256[] countArr;
struct People{
string name;
uint256 favNum;
}
In this function, i set the data of my struct object and then include it in my mapping.
function setPerson(string memory _name,uint256 _id, uint256 _favNum) public {
dataList[_id]= People(_name,_favNum);
countArr.push(_id);
}
This function here gets me the data of my specified struct object.
function getPerson(uint _id) public view returns(string memory,uint256){
return (dataList[_id].name, dataList[_id].favNum);
}
Now here is the function i think that is causing me trouble because in this function i want to return not the data of a single People object but all of my data and whenever i run this function on my REMIX IDE console it shows me the error: call to MyContract.getAllData errored: VM error: revert. revert
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
function getAllData()public view returns(People[] memory){
uint256 count = countArr.length;
uint256 i = 0;
People[] memory outputL= new People[](count);
while(count >= 0){
(string memory nam,uint256 num) = getPerson(count-1);
People memory temp = People(nam,num);
outputL[i]=temp;
count--;
i++;
}
return outputL;
}
}
Can anyone help and explain what is wrong and how can i get it running?
This version of the getAllData function works as you expect:
function getAllData() public view returns (People[] memory) {
uint256 count = countArr.length;
People[] memory outputL = new People[](count);
while(count > 0) {
count--;
(string memory nam, uint256 num) = getPerson(countArr[count]);
People memory temp = People(nam, num);
outputL[count] = temp;
}
return outputL;
}
Feel free to ask if you have any questions about the changes.
I am trying to write a smart contract for jackpot game which calculates users' rate and randomly selects one user but I am getting "The called function should be payable if you send value and the value you send should be less than your current balance." error when I try to execute sendToWinner() function.
Note: Please don't mind the logical errors I am aware of the logical errors this is for training my Solidity writing skills.
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
contract Jackpot {
uint256 public pot;
mapping (address => uint256) public balances;
address[] public participators;
address public minter;
constructor(){
minter = msg.sender;
}
function addToPot() public payable {
balances[msg.sender] += msg.value;
pot += msg.value;
participators.push(msg.sender);
}
modifier onlyOwner {
require(msg.sender == minter);
_;
}
function random() public view returns(uint){
return uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp)))%100;
}
function sendToWinner() payable public onlyOwner {
uint8[100] memory participatorsRates;
uint8 rate;
uint8 participatorsRatesIndex=0;
for(uint8 participatorIndex = 0; participatorIndex<participators.length; participatorIndex++){
rate = uint8(balances[participators[participatorIndex]]*100/pot);
for(; participatorIndex<rate ; participatorsRatesIndex++){
participatorsRates[participatorsRatesIndex] = participatorIndex;
}
balances[participators[participatorIndex]]=0;
}
uint8 winningParticipatorIndex = participatorsRates[random()];
payable(participators[winningParticipatorIndex]).transfer(pot);
}
}
1) payable it's a modifier, so you have to write after "public"
`function sendToWinner() public payable onlyOwner {}`
2) don't use .transfer, use call{value: amount}("") instead.
so it will be:
function sendToWinner() public payable onlyOwner {
uint8[100] memory participatorsRates;
uint8 rate;
uint8 participatorsRatesIndex=0;
for(uint8 participatorIndex = 0; participatorIndex<participators.length; participatorIndex++){
rate = uint8(balances[participators[participatorIndex]]*100/pot);
for(; participatorIndex<rate ; participatorsRatesIndex++){
participatorsRates[participatorsRatesIndex] = participatorIndex;
}
balances[participators[participatorIndex]]=0;
}
uint8 winningParticipatorIndex = participatorsRates[random()];
(bool success, ) = payable(participators[winningParticipatorIndex]).call{value:pot}("");
require(success, "Transfer failed.");
}
see:
Is transfer() still safe after the Istanbul update?
https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/
3) be sure to have enough balance
I just found out that I have used wrong variable at nested loop in sendToWinner() function:
for(uint8 participatorIndex = 0; participatorIndex<participators.length; participatorIndex++){
rate = uint8(balances[participators[participatorIndex]]*100/pot);
for(; participatorIndex<rate ; participatorsRatesIndex++){
participatorsRates[participatorsRatesIndex] = participatorIndex;
}
balances[participators[participatorIndex]]=0;
}
For for(; participatorIndex<rate ; participatorsRatesIndex++){ instead participatorIndex I should have written participatorsRatesIndex. Because it became infinite loop it couldn't work but now it is working.