Check that object is null in solidity mapping - ethereum

I have this solidity mapping
mapping (string => Ticket) public myMapping;
I want to check if myMapping[key] exists or not. How can I check?

The entire storage space is virtually initialized to 0 (there is no undefined).
So you have to compare the value to the 0 value for your type.
For example, mapping[key] == address(0x0) or mapping[key] = bytes4(0x0).

There is no direct method to check whether the mapping has particular key. But you can check if mapping property has value or not. The following example considered that the Ticket is the struct with some property.
pragma solidity >=0.4.21 <0.6.0;
contract Test {
struct Ticket {
uint seatNumber;
}
mapping (string => Ticket) myMapping;
function isExists(string memory key) public view returns (bool) {
if(myMapping[key].seatNumber != 0){
return true;
}
return false;
}
function add(string memory key, uint seatNumber) public returns (bool){
myMapping[key].seatNumber = seatNumber;
return true;
}
}

pragma solidity ^0.8.0;
contract BookLibNew{
address public owner;
constructor() public{
owner = msg.sender;
}
modifier onlyOwner(){
require(msg.sender == owner);
_;
}
struct bookDet{
uint bookId;
string bookTitle;
string bookAuthor;
}
mapping (uint8 => bookDet) public bookLib;
function addBookLib(uint8 _bookId, string memory _bookTitle, string memory _bookAuthor)
public onlyOwner {
require(bookLib(_bookId) == false, "Error: Book already exists");
bookLib[_bookId].bookTitle = _bookTitle;
bookLib[_bookId].bookAuthor = _bookAuthor;
}
function readBookDetails(uint8 _bookId) public view returns(string memory, string memory){
return(bookLib[_bookId].bookTitle, bookLib[_bookId].bookAuthor);
}
}

Related

Ordinal Number Function in Remix Solidity

I want to create a new function based on these codes below, that it can just fill in the ordinal number (first student is started by 1) to track out the struct student info in this case.
That's mean after I give the data of this first student to the struct by addInfo function:["Simon", 20, "CA USA", 10] Then my expected new function is that I just fill in this unit: 1, then it will appear this student detail
\`
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ReferenceTypes {
address public owner;
struct student {
string Name;
uint Age;
string BirthPlace;
uint8 Marks;
}
constructor() {
owner = msg.sender;
}
mapping (address => student) public Info;
address[] public student_Info;
function addInfo(student memory _student, address _address) public {
require(owner == msg.sender, "Only admin can add Info!!!");
Info[_address] = _student;
student_Info.push(_address);
}
function count() public view returns(uint) {
return student_Info.length;
}
}
\`
Thanks so much guys
I tried a new mapping but failed
You can make another mapping that leads to your mapping Info.
uint public studentsCounter;
mapping (uint => mapping (address => student)) public Info;
function addInfo(student memory _student, address _address) public returns(uint){
require(owner == msg.sender, "Only admin can add Info!!!");
Info[studentsCounter][_address] = _student;
studentsCounter++;
student_Info.push(_address);
return studentsCounter-1;
}
Thus you can reach your struct by passing studentId(studentCounter) which addInfo returns and students address.
Another approach is to remake you array of addresses.
student[] public student_Info;
And push struct in this array.
function addInfo(student memory _student, address _address) public {
require(owner == msg.sender, "Only admin can add Info!!!");
Info[_address] = _student;
student_Info.push(_student);
}
So now you can display studentsInfo buy passing index in student_Info array.

Error :The transaction has been reverted to the initial state

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
contract modifierExample{
address admin ;
constructor() public {
admin == msg.sender;
}
modifier isAdmin {
require(admin == msg.sender,"you are not the owner");
_;
}
modifier isExp(uint exp) {
if(exp >= 5)
_;
else
revert("you are not experienced");
}
struct employeeDetails{
uint iD;
string name;
uint age;
}
mapping (uint => employeeDetails) getDetailsByNum;
function enterDetails(uint number,
uint iD,
string memory name,
uint age) public isAdmin isExp(5) {
employeeDetails memory EmployeeDetails = employeeDetails(iD,name,age);
getDetailsByNum[number] = EmployeeDetails;
}
function getDetailsByNumber(uint number) public view returns (employeeDetails memory) {
return getDetailsByNum[number];
}
}
Why did I encounter this error?????
After entering the details it is throwing me an error as mentioned below
transact to modifierExample.enterDetails errored: VM error: revert.
revert
The transaction has been reverted to the initial state.
Reason provided by the contract: "you are not the owner".
Debug the transaction to get more information.
Your enterDetails() function uses the isAdmin modifier.
As per the following code, any function that uses the isAdmin modifier, can be executed only by the address that deployed the contract.
address admin ;
constructor() public {
admin == msg.sender;
}
modifier isAdmin {
require(admin == msg.sender,"you are not the owner");
_;
}
You're getting the you are not the owner error because you're trying to execute the function from some other address than the admin.

How to interact with mapping of mappings for structs in solidity?

I have created struct with nested mapping. Consider the following piece of code written inside the contract in solidity:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract TestContract {
struct Item {
uint itemId;
uint itemValue;
}
struct OverlayingItemStruct {
mapping(uint => Item) items;
uint overlayingId;
uint itemsCount;
}
mapping(uint => OverlayingItemStruct) public overlayingItems;
uint public overlayCount;
function addOverlayingItemsStruct(uint _value) external {
overlayCount ++;
mapping(uint => Item) memory items;
items[1] = Item(1, _value);
overlayingItems[overlayCount] = OverlayingItemStruct(items, 1, 1);
}
function addItem(uint _value, uint _overlayId) external {
OverlayingItemStruct storage overlay = overlayingItems[_overlayId];
overlay.itemsCount ++;
overlay.items[overlay.itemsCount] = Item(overlay.itemsCount, _value);
}
}
When compiling the above code, I am getting the error:
TypeError: Uninitialized mapping. Mappings cannot be created dynamically, you have to assign them from a state variable.
--> TestC.sol:21:5:
|
21 | mapping(uint => Item) memory items;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Not sure, how to handle this error.
Secondly, needed to confirm if the method to add new values in the nested mapping dictionary is correct?
A mapping cannot be declare inside a function and in memory state. This type has only storage state.
Said this, to pass a mapping into a struct, you can set the key of nested mapping and pass relative struct inside it.
I tried to adjust your smart contract like this:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract TestContract {
struct Item {
uint itemId;
uint itemValue;
}
struct OverlayingItemStruct {
mapping(uint => Item) items;
uint overlayingId;
uint itemsCount;
}
mapping(uint => OverlayingItemStruct) public overlayingItems;
uint public overlayCount;
function addOverlayingItemsStruct(uint _value) external {
overlayCount ++;
// NOTE: I declared a new Item struct
Item memory item = Item(1, _value);
// NOTE: I set into items mapping key value 1, Item struct created in row above this
overlayingItems[overlayCount].items[1] = item;
}
function addItem(uint _value, uint _overlayId) external {
OverlayingItemStruct storage overlay = overlayingItems[_overlayId];
overlay.itemsCount ++;
overlay.items[overlay.itemsCount] = Item(overlay.itemsCount, _value);
}
}

Solidity CRUD trying to call All data return instead of one by one using ID

I have created a solidity that record data CRUD like where I can create read update delete but I want to create a readAll function wondering how can I write in solidity since I write like below it does not work. For calling with id it return the correct but not readAll. Looking forward for your help <3
example
function readAllTask() public view returns (uint, uint256, uint256) {
return (tasks.id, tasks.stackAddress, tasks.nftId); <============= return everything
}
pragma solidity ^0.8.6;
contract RecordData {
struct Task {
uint id;
uint256 stackAddress;
uint256 nftId;
}
Task[] tasks;
uint nextId; // default value 0, add public to see the value
function createTask(uint256 _stackAddress, uint256 _nftId) public {
tasks.push(Task(nextId, _stackAddress, _nftId));
nextId++;
}
function findIndex(uint _id) internal view returns (uint) {
for (uint i = 0; i < tasks.length; i++) {
if (tasks[i].id == _id) {
return i;
}
}
revert("Task not found");
}
function updateTask(uint _id, uint256 _stackAddress, uint256 _nftId) public {
uint index = findIndex(_id);
tasks[index].stackAddress = _stackAddress;
tasks[index].nftId = _nftId;
}
function readTask(uint _id) public view returns (uint, uint256, uint256) {
uint index = findIndex(_id);
return (tasks[index].id, tasks[index].stackAddress, tasks[index].nftId);
}
function deleteTask(uint _id) public {
uint index = findIndex(_id);
delete tasks[index];
}
}
You can return an array of structs:
function readAllTask() public view returns (Task[] memory) {
return tasks;
}
I think you have reason to do it, but just a remind that saving the data into blockchain is not a good deal, due to the high cost.
If you would like to return all the task, then simply make the tasks public. Solidity automatically assign a get function for it.
If you would like to get some specific content of task struct, then consider something like this:
function readAllTask() public view returns (uint, uint256, uint256 [] memory) {
// something
}

Solidity: Retrieving values of Array of Structs in Mapping

I have some solidity code where I am attempting to gather the ids which are a value stored on a Struct. I have a mapping where the key is an address, and the value is an array of Structs. Whenever I execute the getMediaByAddress function I get an invalid OpCode error. Any help would be greatly appreciated.
pragma solidity ^0.4.24;
contract MediaGallery {
address owner;
uint counter;
struct MediaAsset {
uint id;
string name;
address author;
uint createDate;
string[] tags;
string mediaHash;
}
mapping(address => MediaAsset[]) public mediaDatabase;
constructor () {
owner = msg.sender;
}
function addMedia(string _name, string _mediaHash) public returns (bool success) {
MediaAsset memory currentMedia;
currentMedia.id = counter;
currentMedia.name = _name;
currentMedia.author = msg.sender;
currentMedia.createDate = now;
currentMedia.mediaHash = _mediaHash;
mediaDatabase[msg.sender].push(currentMedia);
return true;
}
function addTag(uint _id, string _tag) public returns (bool success) {
mediaDatabase[msg.sender][_id].tags.push(_tag);
return true;
}
function getMediaByAddress(address _user) public view returns (uint[]) {
uint[] memory mediaAssetIds = new uint[](mediaDatabase[_user].length);
uint numberOfMediaAssets = 0;
for(uint i = 1; i <= mediaDatabase[_user].length; i++) {
mediaAssetIds[numberOfMediaAssets] = mediaDatabase[_user][i].id;
numberOfMediaAssets++;
}
return mediaAssetIds;
}
}
You're trying to read past the end of the array. Your loop variable i has an off-by-one error. Its greatest value is mediaDatabase[_user].length, which is 1 past the end of the array. Try this instead:
for (uint i = 0; i < mediaDatabase[_user].length; i++) {