I'm running into a problem with solidity with structures containing arrays, can you help me see what I'm missing?Any help would be greatly appreciated!
struct Info {
uint a;
uint256 b;
uint[] data;
}
mapping(address => Info) infos;
function set() public {
infos[msg.sender].a = 1;
infos[msg.sender].b = 2;
infos[msg.sender].data.push(3);
}
function get() public {
infos[msg.sender].a; //yes It is equal to 1
infos[msg.sender].b; //yes It is equal to 2
infos[msg.sender].data[0]; //The problem here is that anyone calling this function can read data[0]=3
}
I am a little confused as to what you require, but first solution I have provided modifies your Smart Contract such that mapping object infos and the getter function is both private (available only in the Contract defined).
contract test{
struct Info {
uint a;
uint b;
uint[] data;
}
mapping(address => Info) private infos;
function set() public {
infos[msg.sender].a = 1;
infos[msg.sender].b = 2;
infos[msg.sender].data.push(3);
}
function get() private view{
infos[msg.sender].a; //yes It is equal to 1
infos[msg.sender].b; //yes It is equal to 2
infos[msg.sender].data[0]; //The problem here is that anyone calling this function can read data[0]=3
} }
Second solution is to add something called 'require' in the getter function so that only the person who deploys the Smart Contract can view the array index. The constructor function assigns the person who deploys the contract as the 'owner'.
contract test{
struct Info {
uint a;
uint b;
uint[] data;
}
address owner;
constructor() {
owner = msg.sender;
}
mapping(address => Info) infos;
function set() public {
infos[msg.sender].a = 1;
infos[msg.sender].b = 2;
infos[msg.sender].data.push(3);
}
function get() public view{
infos[msg.sender].a; //yes It is equal to 1
infos[msg.sender].b; //yes It is equal to 2
require(owner == msg.sender, 'you cannot read this data, you are not the owner!');
infos[msg.sender].data[0]; //The problem here is that anyone calling this function can read data[0]=3
}
}
Let me know if I have misunderstood your question.
Related
contract Counter {
uint public Count = 0;
event Increment(uint value);
event Decrement(uint value);
function getCount() view public returns(uint) {
return Count;
}
function Increment() public {
Count += 1;
emit Increment(Count);
}
function Decrement() public {
count -= 1;
emit Decrement(Count);
}
}
please what is already defined or wrong
As said #Yilmaz, your issue refers that events and functions name have the same name.
To solve this issue, you must change name to events or function names.
In the following lines, I put an example how you will solve it:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Counter {
uint public Count = 0;
// NOTE: I changed name to these two events
event EventIncrement(uint value);
event EventDecrement(uint value);
function getCount() view public returns(uint) {
return Count;
}
function Increment() public {
Count += 1;
emit EventIncrement(Count);
}
function Decrement() public {
Count -= 1;
emit EventDecrement(Count);
}
}
I'm trying to test out a smart contract using Remix.
They compile fine, but when I deploy thz contractenter code here I get this error:
This contract may be abstract, not implement an abstract parent's methods completely or not invoke an inherited contract's constructor correctly.
Anyone know what could be going on? Thanks!
pragma solidity ^0.8.7;
interface UDL_SC_lifecycle_manager {
struct TP {
uint id;
}
struct OP {
uint id;
}
struct BP{
uint id;
}
//ContractDescriptionMetaData
struct CDMD {
uint ID;
address providerAdress;
TP TechnicalPerspective;
OP OperationalPerspective;
BP BusnissPerspective;
}
function PublishDesc(CDMD memory ContractDescription, address provider) external ;
function UpdateDesc(CDMD memory ContractDescription, address provider) external ;
function DestroyDesc(address contractadr, uint contractID) external returns(bool);
}
abstract contract SmartRegistryService is UDL_SC_lifecycle_manager{
mapping(address => CDMD) CDMDS;
address contractAdresse;
address proprietaire;
event DescriptionPublished(string _msg);
event DescriptionUpdated (string _msg);
event NotExist (string _msg);
event Deleted (string _msg);
function publishdesc (CDMD memory NVContractDescriptionMetaData, address providerAdress) public {
CDMDS[providerAdress] = NVContractDescriptionMetaData;
emit DescriptionPublished(" smart contract published successfully!");
}
modifier ProviderOnly(address provider){
require(msg.sender == provider);
_;
}
function updatedesc (CDMD memory NVContractDescriptionMetaData, address providerAddress, uint contractID) public {
bool statue = false;
CDMD storage newContractDescriptionMetaData = CDMDS[providerAddress];
if((newContractDescriptionMetaData.ID== contractID)&&(newContractDescriptionMetaData.providerAdress == providerAddress)){
statue = true;
CDMDS[providerAddress] = NVContractDescriptionMetaData;
emit DescriptionUpdated("smart contract updated successfully!");
}else{
emit NotExist("smart contract notExist!");
}
}
function destroydesc(address providerAddress, uint contractID) public {
CDMD storage newContractDescriptionMetaData = CDMDS[providerAddress];
if (newContractDescriptionMetaData.ID == contractID) {
delete CDMDS[providerAddress];
emit Deleted("smart contract deleted successfully!");
}
}
}
I'm starting to approach with Solidity (current version 0.8.0) smart contracts, but I can't understand why the compiler print me an error during the push.
The problem is the following: I'm trying to push an element on array in struct but compile failed with error: Copying of type struct memory[] memory to storage not yet supported.
Here my example:
contract TestNFT is ERC721, Ownable {
struct Child {
string name;
}
struct Father {
string name;
Child[] childs;
}
mapping(uint256 => Child) private _childs;
uint256 nextChild = 0;
mapping(uint256 => Father) private _fathers;
uint256 nextFather = 0;
constructor(string memory name, string memory symbol)
ERC721(name, symbol)
{}
function mint(
string memory name
) public onlyOwner {
_safeMint(msg.sender, nextCharacter);
_childs[nextChild] = Child(name);
nextChild++;
}
function mintFather(string memory name) public onlyOwner {
_safeMint(msg.sender, nextClan);
_fathers[nextFather] = Father(name, new Child[](0));
nextFather++;
}
function insertChildToFather(uint256 fatherId, uint256 childId)
public
onlyOwner
{
Child memory child = _childs[childId];
_fathers[fatherId].childs.push(child);
}
}
How can I fix the insertChildToFather function?
I am trying to create a public funcion that returns an array,
this is the error
Return argument type mapping(uint256 => struct ItemList.Item storage
ref) is not implicitly convertible to expected type (type of first
return variable) uint256[] memory.
pragma solidity ^0.5.0;
contract ItemList {
uint public itemCount = 0;
mapping(uint256 => Item) public items;
event ItemCreated (
uint id,
string proofdocument
);
struct Item {
uint id;
string proofdocument;
}
constructor() public {
}
function createItem(string memory _proofdocument) public {
itemCount++;
items[itemCount] = Item(itemCount, _proofdocument);
emit ItemCreated(itemCount, _proofdocument);
}
function getItems() public pure returns(uint256[] memory ) {
return items; <----------ERROR
}
}
Thanks Andrea
You can get every item in the loop via web3.js library
const array = []
for (let i = 0; i < itemCount; itemCount += 1) {
array.push(contract.getItem(i)) // where getItem do items[I] in solidity
}
Or you can use pragma experimental version:
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;
contract ItemList {
uint public itemCount = 0;
struct Item {
uint id;
string proofdocument;
}
Item[] items;
constructor() public {}
function createItem(string memory _proofdocument) public {
itemCount++;
items.push(Item(itemCount, _proofdocument));
}
function getItems() external view returns(Item[] memory) {
return items;
}
}
I am creating a dapp to transfer ownership of the contract from one address to another using testrpc. However,I keep encountering this problem. I have tried using sentransaction method to do perform this ownership change.Perhaps I'm calling the exchange in a wrong manner.
Solidity version 0.4.4
web3 "version": "0.20.2"
web3.js:3127 Uncaught Error: VM Exception while processing transaction: invalid opcode
at Object.InvalidResponse (web3.js:3127)
at RequestManager.send (web3.js:6332)
at Eth.send [as sendTransaction] (web3.js:5066)
at SolidityFunction.sendTransaction (web3.js:4122)
at SolidityFunction.execute (web3.js:4208)
at transferOwnership (luxcure_manu.html:309)
at HTMLButtonElement.onclick (luxcure_manu.html:378
Full solidity contract as of yet.
pragma solidity ^0.4.4;
// TODO: Hash of the cert through IPFS Hash
// Transfer ownership of smart contract
contract LuxSecure {
address public contract_owner; //Manufacturer/owner
//string public current_owner; //Current Owner of good
bytes32 public model; //Model
mapping(uint => address) public owners; //list of owners
uint256 public owners_count;
bytes32 public status; // (Public(Owned by no one), Private(Bought by another entity),stolen(Stolen from public or private))
bytes32 public date_manufactured; //Time
// Set manufacturer of the Good RUN ONCE ONLY
function manufacturer() public{
if(owners_count == 0){
contract_owner = msg.sender;
}
}
//Modifier that only allows owner of the bag to Smart Contract AKA Good to use the function
modifier onlyOwner(){
require(msg.sender == contract_owner);
_;
}
// Add a new product to the blockchain with a new serial
function addNewGoods(bytes32 _model,bytes32 _status, bytes32 _date_manufactured) public returns(bool made) {//Declare Goods struct
setOwner(msg.sender);
model = _model;
status = _status;
date_manufactured = _date_manufactured;
return true;
}
//This function transfer ownership of contract from one entity to another
function transferOwnership(address _newOwner) public onlyOwner(){
require(_newOwner != address(0));
contract_owner = _newOwner;
}
//Set the KEY to uint256 and VALUE owner Ethereum Address
function setOwner(address owner)public{
owners_count += 1 ;
owners[owners_count] = owner;
}
//Get the previous owner in the mappings
function previousOwner()constant public returns(address){
if(owners_count != 0){
uint256 previous_owner = owners_count - 1;
return owners[previous_owner];
}
}
// Getter Methods
function getManufacturer() constant public returns(address){
return contract_owner;
}
function getCurrentOwner() constant public returns(address){
return owners[owners_count] ;
}
function getOwnerCount() constant public returns(uint256){
return owners_count;
}
function getModel() constant public returns(bytes32){
return model;
}
function getStatus() constant public returns(bytes32){
return status;
}
function getDateManufactured() constant public returns(bytes32){
return date_manufactured;
}
}// end of LuxSecure
Javascript to perform the transfer of ownership
function transferOwnership(){
var account_to_transfer = document.getElementById("ethereumaddress").value;
contract.transferOwnership(account_to_transfer,{
from:web3.eth.accounts[0],
gas:4000000
});
}
I don't see any particular mistake in your code. Maybe a bad formatting on the front-side, but can't guess for sure as we have partial front here.
I don't know if it will be some help but sometimes, using truffle, it happened to me to have some functions that returned bad opcode from testrpc/ganache-cli while no apparent error was in the code.
Deleting the ABI, recompiling the smart-contracts to get a brand new ABI and then redeploying the contracts solved the problem.