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;
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/
Whenever i pass parameter in adoptAxie function through following error :-
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.
Debug the transaction to get more information.
Please Help me
pragma solidity ^0.4.19;
import "./Pausable.sol";
import "./SafeMath.sol";
import "./HasNoEther.sol";
contract AxiePresale is HasNoEther, Pausable {
using SafeMath for uint256;
// No Axies can be adopted after this end date: Friday, March 16, 2018 11:59:59 PM GMT.
uint256 constant public PRESALE_END_TIMESTAMP = 1649142348;
uint8 constant public CLASS_BEAST = 0;
uint8 constant public CLASS_AQUATIC = 2;
uint8 constant public CLASS_PLANT = 4;
uint256 constant public INITIAL_PRICE_INCREMENT = 1600 szabo; // 0.0016 Ether
uint256 constant public INITIAL_PRICE = INITIAL_PRICE_INCREMENT;
uint256 constant public REF_CREDITS_PER_AXIE = 5;
mapping (uint8 => uint256) public currentPrices;
mapping (uint8 => uint256) public priceIncrements;
mapping (uint8 => uint256) public totalAxiesAdopted;
mapping (address => mapping (uint8 => uint256)) public axiesAdopted;
mapping (address => uint256) public referralCredits;
mapping (address => uint256) public axiesRewarded;
uint256 public totalAxiesRewarded;
event AxiesAdopted(
address indexed adopter,
uint8 indexed clazz,
uint256 quantity,
address indexed referrer
);
event AxiesRewarded(address indexed receiver, uint256 quantity);
event AdoptedAxiesRedeemed(address indexed receiver, uint8 indexed clazz, uint256 quantity);
event RewardedAxiesRedeemed(address indexed receiver, uint256 quantity);
function AxiePresale() public {
priceIncrements[CLASS_BEAST] = priceIncrements[CLASS_AQUATIC] = priceIncrements[CLASS_PLANT] = INITIAL_PRICE_INCREMENT;
currentPrices[CLASS_BEAST] = currentPrices[CLASS_AQUATIC] = currentPrices[CLASS_PLANT] = INITIAL_PRICE;
}
function axiesPrice(
uint256 beastQuantity,
uint256 aquaticQuantity,
uint256 plantQuantity
)
public
view
returns (uint256 totalPrice)
{
uint256 price;
(price,,) = _axiesPrice(CLASS_BEAST, beastQuantity);
totalPrice = totalPrice.add(price);
(price,,) = _axiesPrice(CLASS_AQUATIC, aquaticQuantity);
totalPrice = totalPrice.add(price);
(price,,) = _axiesPrice(CLASS_PLANT, plantQuantity);
totalPrice = totalPrice.add(price);
}
function adoptAxies(
uint256 beastQuantity,
uint256 aquaticQuantity,
uint256 plantQuantity,
address referrer
)
public
payable
whenNotPaused
{
require(now <= PRESALE_END_TIMESTAMP);
require(beastQuantity <= 3);
require(aquaticQuantity <= 3);
require(plantQuantity <= 3);
address adopter = msg.sender;
address actualReferrer = 0x0;
// An adopter cannot be his/her own referrer.
if (referrer != adopter) {
actualReferrer = referrer;
}
uint256 value = msg.value;
uint256 price;
if (beastQuantity > 0) {
price = _adoptAxies(
adopter,
CLASS_BEAST,
beastQuantity,
actualReferrer
);
require(value >= price);
value -= price;
}
if (aquaticQuantity > 0) {
price = _adoptAxies(
adopter,
CLASS_AQUATIC,
aquaticQuantity,
actualReferrer
);
require(value >= price);
value -= price;
}
if (plantQuantity > 0) {
price = _adoptAxies(
adopter,
CLASS_PLANT,
plantQuantity,
actualReferrer
);
require(value >= price);
value -= price;
}
msg.sender.transfer(value);
// The current referral is ignored if the referrer's address is 0x0.
if (actualReferrer != 0x0) {
uint256 numCredit = referralCredits[actualReferrer]
.add(beastQuantity)
.add(aquaticQuantity)
.add(plantQuantity);
uint256 numReward = numCredit / REF_CREDITS_PER_AXIE;
if (numReward > 0) {
referralCredits[actualReferrer] = numCredit % REF_CREDITS_PER_AXIE;
axiesRewarded[actualReferrer] = axiesRewarded[actualReferrer].add(numReward);
totalAxiesRewarded = totalAxiesRewarded.add(numReward);
AxiesRewarded(actualReferrer, numReward);
} else {
referralCredits[actualReferrer] = numCredit;
}
}
}
function redeemAdoptedAxies(
address receiver,
uint256 beastQuantity,
uint256 aquaticQuantity,
uint256 plantQuantity
)
public
onlyOwner
returns (
uint256 /* remainingBeastQuantity */,
uint256 /* remainingAquaticQuantity */,
uint256 /* remainingPlantQuantity */
)
{
return (
_redeemAdoptedAxies(receiver, CLASS_BEAST, beastQuantity),
_redeemAdoptedAxies(receiver, CLASS_AQUATIC, aquaticQuantity),
_redeemAdoptedAxies(receiver, CLASS_PLANT, plantQuantity)
);
}
function redeemRewardedAxies(
address receiver,
uint256 quantity
)
public
onlyOwner
returns (uint256 remainingQuantity)
{
remainingQuantity = axiesRewarded[receiver] = axiesRewarded[receiver].sub(quantity);
if (quantity > 0) {
// This requires that rewarded Axies are always included in the total
// to make sure overflow won't happen.
totalAxiesRewarded -= quantity;
RewardedAxiesRedeemed(receiver, quantity);
}
}
/**
* #dev Calculate price of Axies from the same class.
* #param clazz The class of Axies.
* #param quantity Number of Axies to be calculated.
*/
function _axiesPrice(
uint8 clazz,
uint256 quantity
)
private
view
returns (uint256 totalPrice, uint256 priceIncrement, uint256 currentPrice)
{
priceIncrement = priceIncrements[clazz];
currentPrice = currentPrices[clazz];
uint256 nextPrice;
for (uint256 i = 0; i < quantity; i++) {
totalPrice = totalPrice.add(currentPrice);
nextPrice = currentPrice.add(priceIncrement);
if (nextPrice / 100 finney != currentPrice / 100 finney) {
priceIncrement >>= 1;
}
currentPrice = nextPrice;
}
}
/**
* #dev Adopt some Axies from the same class.
* #param adopter Address of the adopter.
* #param clazz The class of adopted Axies.
* #param quantity Number of Axies to be adopted, this should be positive.
* #param referrer Address of the referrer.
*/
function _adoptAxies(
address adopter,
uint8 clazz,
uint256 quantity,
address referrer
)
private
returns (uint256 totalPrice)
{
(totalPrice, priceIncrements[clazz], currentPrices[clazz]) = _axiesPrice(clazz, quantity);
axiesAdopted[adopter][clazz] = axiesAdopted[adopter][clazz].add(quantity);
totalAxiesAdopted[clazz] = totalAxiesAdopted[clazz].add(quantity);
AxiesAdopted(
adopter,
clazz,
quantity,
referrer
);
}
/**
* #dev Redeem adopted Axies from the same class.
* #param receiver Address of the receiver.
* #param clazz The class of adopted Axies.
* #param quantity Number of adopted Axies to be redeemed.
*/
function _redeemAdoptedAxies(
address receiver,
uint8 clazz,
uint256 quantity
)
private
returns (uint256 remainingQuantity)
{
remainingQuantity = axiesAdopted[receiver][clazz] = axiesAdopted[receiver][clazz].sub(quantity);
if (quantity > 0) {
// This requires that adopted Axies are always included in the total
// to make sure overflow won't happen.
totalAxiesAdopted[clazz] -= quantity;
AdoptedAxiesRedeemed(receiver, clazz, quantity);
}
}
}
There is a function called ownerOf(uint id) that return the address of this specific id. I want to write a function that gets total supply and pass each total supply id to ownerOf and the return address of the owner of that ID I passed and save in an array.
here is my code
and its says: ERC721: owner query for nonexistent token
function GetAllNftOwnerAddress()
public
view
returns (address[] memory)
{
uint256 total = totalSupply();
address[] memory tokenIds;
for (uint256 i; i < total; i++) {
tokenIds[i] = ownerOf(i);
}
return tokenIds;
}
This raised when there's no item with id i in the _owners array.
This could happen when the totalSupply() is different from the length of _owners. Please make sure that the value of totalSupply sync with the _owners.
E.g.
_owners[0] = '0x11'
_owners[1] = '0x22'
_owners[2] = '0x33'
_owners[3] = '0x44'
totalSupply = 4
When we do:
delete _owners[2]
total -= 1
And then try to access:
for (uint256 i; i < total; i++) {
tokenIds[i] = ownerOf(i);
}
You'll get an exception when i == 2 because the _owner[2] = 0x0.
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.