Solidity inserting array as map value after _setTokenURI on ERC721 - arrays

I want to assign an array as a value type of a map named dictBasic after function _mint and _setTokenURI from erc721. something like this:
contract Implement721 is ERC721URIStorage{
uint256 public tokenCounter;
mapping(address => uint[]) public dictBasic;
constructor() ERC721("alvinChris", "ACH") {
tokenCounter = 100;
}
function saveData(address _address_sender, string memory _tokenURI)
public returns(address, uint256){
uint256 newItemId = tokenCounter;
_mint(_address_sender, newItemId); //mint function
_setTokenURI(newItemId, _tokenURI); //setTokenURI
//inserting to map
dictBasic[_address_sender].push(tokenCounter);
tokenCounter = tokenCounter + 1;
return (_address_sender, newItemId);
}
I can assign successfully, but the question is can I make sure that the _mint and _setTokenURI is done before inserting array to Map. can someone give me the example on handling this case.
The idea that come in my mind is like IF logic, when _mint and _setTokenURI is not done, then pending assigning value to Map until its done.
Thankyou for the help

Related

How to change variable's value and use return as a view function in solidity

I've initialized a votes array and two functions to store the votes in our array as :
uint[2] votes = [0,0];
function vote_a() public{
votes[0] += 1;
}
function vote_b() public{
votes[1] += 1;
}
Now, I've created a "results" function which should return a string "tie", "a wins" or "b wins" on the basis of number of votes while also reassigning the number of votes to 0
function results() public returns(string memory){
uint a = votes[0];
uint b = votes[1];
votes[0]=0;
votes[1]=0;
if (a==b)
return "tie";
else if (a>b)
return "a wins";
else
return "b wins";
}
but it does not show the returned result in remix ide like a view function. And I cannot modify the state of the function to view as it'd throw an error for changing value of votes array elements. Is there any way to achieve both conditions.
This happen when you'alterating state variables defined in view functions.
Thus, view functions can only reads data from your smart contract.
To solve your issue, I tried to split the content about results() function in two functions. The first function that I called setResults() is a similar to setter functions (in other programming languages), so allows only for contract owner to handle the array values.
Second function, allows you to view the result about the comparison between a and b elements.
In the following lines, I put your smart contract adjusted where I inserted some notes:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Test {
uint[2] votes = [0,0];
address owner;
// NOTE: I set a 'owner' variable with the address value who have deployed for the first time the smart contract
constructor() {
owner = msg.sender;
}
// NOTE: Modifier that allow only for smart contract owner the access to specific function
modifier onlyOwner() {
require(msg.sender == owner, "You're not the owner!");
_;
}
function vote_a() public{
votes[0] += 1;
}
function vote_b() public{
votes[1] += 1;
}
function results() public view returns(string memory){
uint a = votes[0];
uint b = votes[1];
if (a==b)
return "tie";
else if (a>b)
return "a wins";
else
return "b wins";
}
// NOTE: I created a new function that allows you to handle the data inside array
function setResults() public onlyOwner {
votes[0] = 0;
votes[1] = 0;
}
}
IMPORTANT: Before call results() function, remember you to call setResults() for change the array values.

Solidity: Return a mapping from inside a struct

here is my code:
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;
mapping(uint => ProductWithBids) public internalProducts;
struct SecretBids {
uint values;
bool fake;
string secret;
}
struct ProductWithBids {
uint id;
string name;
uint price;
address payable owner;
address payable beneficiary;
bool purchased;
mapping(address => Bid[]) bids;
mapping(address => SecretBids[]) nakedBids;
// Allowed withdrawals of previous bids
mapping(address => uint) pendingReturns;
uint bidsCount;
bool ended;
uint biddingEnd;
uint revealEnd;
address highestBidder;
uint highestBid;
}
function getNakedBids(uint _id)
public
view
returns(SecretBids[] memory product) {
ProductWithBids storage selectedProduct = internalProducts[_id];
return selectedProduct.nakedBids;
}
i need to return the nakedBids but i get the following error :
TypeError: Return argument type mapping(address => struct eShop.SecretBids storage ref[] storage ref) is not implicitly convertible to expected type (type of first return variable) struct eShop.SecretBids memory[] memory.
return selectedProduct.nakedBids;
I get what the error means, i think i have tried everything and looked everywhere. From what i have found is that solidity doesn't support at all this action .Does anyone has any idea what i can try next? If i missed any other important code parts let me know. Thanks in advance.
I also tried :
returns(mapping(address => SecretBids[]) memory nakedBids)
but then i get the following error:
Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
returns(mapping(address => SecretBids[]) memory nakedBids) {
^-----------------------------------------------^
,TypeError: Type mapping(address => struct eShop.SecretBids[]) is only valid in storage because it contains a (nested) mapping.
returns(mapping(address => SecretBids[]) memory nakedBids)
ps: if i change it to storage it complains that Data location must be memory.
By the way, you should move mapping(address => SecretBids[]) nakedBids; out of the struct, and let it be a storage variable on its own.
nakedBids is an array of SecretBids struct.
My answer is based on solidity v0.5.x (hopefully similar to 0.7.4). Return array of struct is not supported in solidity yet. Instead you can return tuple.
returns (uint[] memory, bool[] memory, string[] memory)
I pretty much gave up on the idea of creating a getter. So i got the data i needed in a more direct way. Probably is not the best way but it worked for me. Feel free to share any other solutions.
Here is the code:
function reveal(
uint _id
)
public
payable
{
ProductWithBids storage selectedProduct = internalProducts[_id];
//onlyAfter biddingEnd && onlyBefore revealEnd
require(block.timestamp > selectedProduct.biddingEnd);
require(block.timestamp < selectedProduct.revealEnd);
uint count = selectedProduct.bidsCount;
uint[] memory values = new uint[](count);
bool[] memory fake = new bool[](count);
string[] memory secret = new string[](count);
for (uint i = 0; i < count; i++) {
values[i] = selectedProduct.nakedBids[msg.sender][i].values;
fake[i] = selectedProduct.nakedBids[msg.sender][i].fake;
secret[i] = selectedProduct.nakedBids[msg.sender][i].secret;
}
revealInternal(
values,
fake,
secret,
_id
);
}
I did not go from the start with this solution because i needed the react-js to do it from the front-end and then just pass it in revealInternal(...);

Solidity - initialize string array in struct

I am currently working on my first smart contract. After already reading a few topics out there I still don't have a clue on how to initialize the string array inside my struct.
The idea is that the customer can always choose from a variety of energysources on a homepage which then gets deployed on the smart contract if he's done choosing.
So what would be the best/efficient way to implement this idea onto the blockchain?
pragma solidity ^0.4.23; /* solhint-disable */
contract EnergyContract {
struct EnContract {
uint price;
uint amount;
string[] energysource;
address creator;
}
EnContract[] aContract;
function createContract(uint _price, uint _amount, address _creator) public {
aContract.length += 1;
EnContract storage _EnContract = aContract[aContract.length - 1];
_EnContract.price = _price;
_EnContract.amount = _amount;
_EnContract.creator = _creator;
}
}
The way you declare your array is correct. You don't need to do anything else. You can just start pushing data into the array.

How can i store the results returned by a method into an array for further use? (Java)

I am trying to store the results returned from a method into an array, however I donĀ“t know which would be the best way to do it.
public class Wealth {
METHOD
double taxes() {
return (0.08*riquezaEnCarros) + (0.15*riquezaEnCasas);
ARRAY?
double [] = taxes();
NEW EDIT
double riquezaTotalHijo() {
return riquezaEnEfectivo + riquezaEnCarros + riquezaEnCasas -
impuestosHijo() + riquezaTotalPadre();
}
public ArrayList<Double> list = new ArrayList<>();
list.add(riquezaTotalHijo());
}
If you are using array then we can assume that you want to call method multiple times
Let if you want to call it 5 times
List<double> list = new ArrayList<double>();
for(int i=0; i<5;i++)
{
//Add values to array list
list.add(taxes());
}
//ArrayList list have values now
//Now you can loop on array list to use values
for (double val : list) {
System.out.println(val);
}

SharedObject for Arrays of Object. Can't get correct data when restart flash

I have an array that stored some Object with its data, and I try to store it in my computer.
If I try to load for the data after I've save the data, I could get a correct data.
Exp: [Object Player]
But if I restart the flash, the data seems to be gone.
What is the problem?
private var sharedObject:SharedObject = SharedObject.getLocal("aquarium", "/");
public function save(n:String):void
{
/* player list will only handle the list of all the Players
* each player data will handle by Player class itself.
*/
registerClassAlias("Player", Player)
player = new Player()
player.newPlayer(n, LATEST_VERSION)
playerArray.push(player)
//saving as shared object
sharedObject.data.aquariumData = playerArray
sharedObject.flush()
load()
}
public function load():void
{
if (sharedObject.size > 0)
{
trace("loading player info")
playerArray = sharedObject.data.aquariumData
trace(playerArray)
}
else
{
trace("there's no record")
}
}
Can you please provide the code how you obtain the shared object ?
Do you use var sharedObject:SharedObject = SharedObject.getLocal("sharedObject"); or something like this ?
Apart from that when calling registerClassAlias("Player", Player) before serialization keep in mind that it must be called before extraction of the data also, so the de-serialization will work correctly and returns array of Player objects not array of Object objects.
And ofc closing the sharedObject is very nice practice after flushing :)
P.S. Your code works as far as i've tested it replacing your Player class with other custom class.

Resources