Type bytes32 is not implicitly convertible to expected type string memory. Operator == not compatible with types string memory and string memory - solidity

I am new to Solidity and building a Todo List project.
I still got below error messages in the deductTask function even after using keccak256(abi.encodePacked())
to pack my string variables
error 1 . Type bytes32 is not implicitly convertible to expected type string memory.
error 2 . Operator == not compatible with types string memory and string memory
pragma solidity >=0.4.22 <0.9.0;
contract myTodoList {
// Model a Task
struct Task {
uint id;
string content;
bool completed;
}
// Read/write Tasks
mapping(uint => Task) public Tasks;
// Store Tasks Count
uint public TasksCount = 0;
function addTask (string memory _content) public {
TasksCount ++;
Tasks[TasksCount] = Task(TasksCount, _content, false);
}
Task TaskTemp;
function deductTask (string memory _contentClicked) public {
string memory comparedContent;
uint i ;
for(i = 1; i <= TasksCount; i++) {
TaskTemp = Tasks[i];
comparedContent = TaskTemp.content;
comparedContent = keccak256(abi.encodePacked(comparedContent));
//comparedContent = keccak256(abi.encodePacked(comparedContent));
_contentClicked = keccak256(abi.encodePacked(_contentClicked));
//_contentClicked = keccak256(abi.encodePacked(_contentClicked));
if(_contentClicked == comparedContent ){
delete Tasks[i];
}
}
TasksCount --;
}
constructor () public {
addTask("my first task");
addTask("my second task");
}
}

Related

How to pass array of struct of type voter in solidity?

I want to pass an array of struct to a function. The array is of type voter. So below is my code. But I am getting error as
UnimplementedFeatureError: Copying of type struct Election.voter memory[] memory to storage not yet supported.
struct voter{
string name;
address constituency;
uint age;
bool isVoted;
}
struct constituency{
string name;
voter[] candidates;
}
constituency[] public constituencyRegister;
function addConstituency(string memory _name,voter[] memory _candidates)
public
{
constituency memory c = constituency(_name, _candidates);
constituencyRegister.push(c);
}
In the following line you are trying to assign a memory array of struct to a storage array of struct, since c contains _candidates:
constituencyRegister.push(c);
Instead, you could push to a storage var, get its reference and only then assigning the name and pushing each _candidates element to the array:
pragma solidity ^0.8.0;
contract MuC {
struct voter{
string name;
address constituency;
uint age;
bool isVoted;
}
struct constituency{
string name;
voter[] candidates;
}
constituency[] public constituencyRegister;
function addConstituency(string memory _name,voter[] memory _candidates)
public
{
constituency storage c = constituencyRegister.push();
c.name = _name;
for(uint i = 0; i < _candidates.length; i++) {
c.candidates.push(_candidates[i]);
}
}
}
This is compiling for me with 0.8.9.

Push method for an array of structures

contract task_list {
struct tasksStruct {
string name;
uint32 timestamp;
bool is_done;
}
tasksStruct[] tasks;
function add_task(string _name) public {
tasksStruct newTask = tasksStruct(_name, now, false);
tasks.push(newTask);
}
function show_opened_tasks() public view returns (uint) {
uint count_of_opened_tasks = 0;
for (uint i=0; i<tasks.length; i++){
if (!tasks[i].is_done) {
count_of_opened_tasks += 1;
}
}
}
}
how does pushing for an array of structures work here? and why there is an error out of range of the array?
You're missing the data location for the reference types in the add_task() function. After fixing this, you'll be able to push to the array.
// added location `memory` for `name`
function add_task(string memory _name) public {
// added location `memory` for `newTask`
tasksStruct memory newTask = tasksStruct(_name, uint32(now), false);
tasks.push(newTask);
}
Also you probably want to return the count_of_opened_tasks from the show_opened_tasks() function - otherwise you'll always get returned the default value 0.
function show_opened_tasks() public view returns (uint) {
uint count_of_opened_tasks = 0;
for (uint i=0; i<tasks.length; i++){
if (!tasks[i].is_done) {
count_of_opened_tasks += 1;
}
}
// added return
return count_of_opened_tasks;
}

Solidity: Returns filtered array of structs without 'push'

I have this contract with an array of structs:
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
contract Tickets {
struct Ticket {
uint id;
int val;
}
Ticket[] tickets;
function addTicket(uint id, int val) public returns(bool success) {
Ticket memory newTicket;
newTicket.id = id;
newTicket.val = val;
tickets.push(newTicket);
return true;
}
function getTicket(uint id) public view returns(Ticket memory) {
uint index;
for(uint i = 0; i<tickets.length; i++){
if (tickets[i].id == id) {
index = i;
break;
}
}
Ticket memory t = tickets[index];
return t;
}
function findTickets(int val) public view returns(Ticket[] memory) {
Ticket[] memory result;
for(uint i = 0; i<tickets.length; i++){
if (tickets[i].val == val) {
result.push(tickets[i]); // HERE IS THE ERROR
}
}
return result;
}
}
I need to returns a filtered by val array but when I buil this code: result.push(tickets[i].id); it throw this error:
TypeError: Member "push" is not available in struct Tickets.Ticket memory[] memory outside of storage.
How I can implement the filter without using push ?
Returning dynamic-length array of struct is still a bit tricky in Solidity (even in the current 0.8 version). So I made a little workaround to make it work even in the 0.6.
Determine the result count, you'll need it for step 2.
Create a fixed-length array
Fill the fixed-length array
Return the fixed-length array
function findTickets(int val) public view returns(Ticket[] memory) {
uint256 resultCount;
for (uint i = 0; i < tickets.length; i++) {
if (tickets[i].val == val) {
resultCount++; // step 1 - determine the result count
}
}
Ticket[] memory result = new Ticket[](resultCount); // step 2 - create the fixed-length array
uint256 j;
for (uint i = 0; i < tickets.length; i++) {
if (tickets[i].val == val) {
result[j] = tickets[i]; // step 3 - fill the array
j++;
}
}
return result; // step 4 - return
}

If statement in for loop not filtering out items in solidity

// #param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
// #return _id - list of ids for homes
function listHomesByAddress(string _physicalAddress) public returns(uint [] _id ) {
uint [] results;
for(uint i = 0 ; i<homes.length; i++) {
if(keccak256(homes[i].physicalAddress) == keccak256(_physicalAddress) && homes[i].available == true) {
results.push(homes[i].id);
}
}
return results;
}
The result is supposed to be a list of ids which match the physical address entered however it does not filter through but returns all the available homes.
When I change to using String utils nothing changes.
Here is the whole code:
pragma solidity ^0.4.0;
import "browser/StringUtils.sol";
// #title HomeListing
contract HomeListing {
struct Home {
uint id;
string physicalAddress;
bool available;
}
Home[] public homes;
mapping (address => Home) hostToHome;
event HomeEvent(uint _id);
event Test(uint length);
constructor() {
}
// #param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
function addHome(string _physicalAddress) public {
uint _id = uint(keccak256(_physicalAddress, msg.sender));
homes.push(Home(_id, _physicalAddress, true));
}
// #param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
// #return _id - list of ids for homes
function listHomesByAddress(string _physicalAddress) public returns(uint [] _id ) {
uint [] results;
for(uint i = 0 ; i<homes.length; i++) {
string location = homes[i].physicalAddress;
if(StringUtils.equal(location,_physicalAddress )) {
results.push(homes[i].id);
}
}
return results;
}
}
The part giving you trouble is the line uint[] results;. Arrays declared as local variables reference storage memory by default. From the "What is the memory keyword" section of the Solidity docs:
There are defaults for the storage location depending on which type of variable it concerns:
state variables are always in storage
function arguments are in memory by default
local variables of struct, array or mapping type reference storage by default
local variables of value type (i.e. neither array, nor struct nor mapping) are stored in the stack
The result is you're referencing the first storage slot of your contract, which happens to be Home[] public homes. That's why you're getting the entire array back.
To fix the problem, you need to use a memory array. However, you have an additional problem in that you can't use dynamic memory arrays in Solidity. A workaround is to decide on a result size limit and declare your array statically.
Example (limited to 10 results):
function listHomesByAddress(string _physicalAddress) public view returns(uint[10]) {
uint [10] memory results;
uint j = 0;
for(uint i = 0 ; i<homes.length && j < 10; i++) {
if(keccak256(homes[i].physicalAddress) == keccak256(_physicalAddress) && homes[i].available == true) {
results[j++] = homes[i].id;
}
}
return results;
}

Self Destruct in geth solidity

I found SelfDestruct problem in geth
I didn't call SelfDestruct on my smart contract
but, after restart my server PC which implements geth, my contract suddenly selfdestruct.
I have no sense about this kind of problem.
is there any condition of selfdestruct which I didn't know?
pragma solidity^0.4.19;
contract Dan_v1_1 {
struct DanInfo {
string file_path;
string kor_name;
string personal_key;
string eng_name;
uint8 gradeOfpoomDan;
string danCertificate;
uint[] regDateHistory;
bool flag;
}
mapping (string => DanInfo) danInfo;
mapping (uint => string) indexOfDanInfo;
uint private danInfoCount = 0;
address contractOwner;
function Dan_v1_1() public{
contractOwner = msg.sender;
}
function setInitDanInfo (string file_path,string kor_name, string personal_key,string eng_name,
uint8 gradeOfpoomDan,string danCertificate, uint []regDateHistory, bool flag)
public{
require (keccak256(danInfo[personal_key].personal_key) != keccak256(personal_key));
danInfo[personal_key] = DanInfo(file_path,kor_name, personal_key,eng_name,gradeOfpoomDan,danCertificate,regDateHistory,flag);
indexOfDanInfo[danInfoCount++] = personal_key;
}
function getDanInfoCount () public constant returns(uint) {
return danInfoCount;
}
function getDanInfo (string personal_key) public constant returns(string,string, string, string, uint8, string, uint[], bool) {
DanInfo memory temp = danInfo[personal_key];
return(temp.file_path,temp.kor_name, temp.personal_key, temp.eng_name, temp.gradeOfpoomDan, temp.danCertificate, temp.regDateHistory, temp.flag);
}
function killContract() public{
if(contractOwner == msg.sender) {
selfdestruct(contractOwner);
}
}
}