Hi everyone, i wrote some solidity code, but unfortunately got some error, what's the matter?
I was using HardHat to compile my code and got next error:
Error looks like this:
ParserError: Expected ';' but got 'constructor'
--> contracts/Tree.sol:14:5
Code looks like this:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Tree {
bytes32[] hashes;
string[4] transactions = [
"first transaction",
"second transaction",
"third transaction",
"fourth transaction"
];
constructor() {
for (uint i = 0; i < transactions.length; i++) {
hashes.push(makeHash(transactions[i]));
}
uint count = transactions.length;
uint offset = 0;
while (count > 0) {
for (uint i = 0; i < count - 1; i += 2) {
hashes.push(
keccak256(
abi.encodePacked(
hashes[offset + 1],
hashes[offset + i + 1]
)
)
);
}
offset += count;
count = count / 2;
}
}
function verify(
string memory transaction,
uint index,
bytes32 root,
bytes32[] memory proof
) public pure returns (bool) {
bytes32 hash = makeHash(transaction);
for (uint i = 0; i < proof.length; i++) {
bytes32 element = proof[i];
if (index % 2 == 0) {
hash = keccak256(abi.encodePacked(hash, element));
} else {
hash = keccak256(abi.encodePacked(element, hash));
}
index = index / 2;
}
return root == hash;
}
function encode(string memory input) public pure returns (bytes memory) {
return abi.encodePacked(input);
}
function makeHash(string memory input) public pure returns (bytes32) {
return keccak256(encode(input));
}
}
I'm not able to reproduce your issue. Above provided code is completely Okay and compiles fine.
However, it issue might be that you have missed a semicolon ; at the end of array string transactions while compiling however, replaced here while uploading the code.
Related
I am trying to create a whitelist. I've used a for and if loop to check if the msg.sender already exists in the array. When the whitelist() function is run, no errors are returned, but when I run check(), it tells me the address doesn't exist in the array, same thing with directing fetching the array.
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SelfWhitelist {
address[] public addressWhitelist;
function whitelist() public returns(string memory) {
for(uint i = 0; i < addressWhitelist.length; i++) {
if(addressWhitelist[i] != msg.sender) {
addressWhitelist.push(msg.sender);
return "Whitelisted!";
}
}
return "Already whitelisted!";
}
function check() public view returns (bool){
for(uint i = 0; i < addressWhitelist.length; i++){
if(addressWhitelist[i] == msg.sender)
return true;
}
return false;
}
}
I added this block of code to check for duplicate entries in the array.
for(uint i = 0; i < addressWhitelist.length; i++) {
if(addressWhitelist[i] != msg.sender) {
addressWhitelist.push(msg.sender);
return "Whitelisted!";
}
Expected for no errors and my address being pushed to the array.
The code ran without errors, but nothing was added to the array.
I would use mapping type to hold the whitelisted addresses, then you don't have to loop over the array
contract SelfWhitelist {
mapping(address => bool) public addressWhitelist;
function whitelist() public returns(string memory) {
if (check()) {
return "Already whitelisted!";
}
addressWhitelist[msg.sender] = true;
return "Whitelisted!";
}
function check() public view returns (bool) {
return addressWhitelist[msg.sender];
}
}
And in your code, seems you have logical issues:
for(uint i = 0; i < addressWhitelist.length; i++) {
if(addressWhitelist[i] != msg.sender) {
addressWhitelist.push(msg.sender);
return "Whitelisted!";
}
}
if the array is empty, the loop never executes, so nothing will be added
if the first item is not msg.sender, msg.sender will be whitelisted, even though it might be already whitelisted.
I am trying to convert address string to type address in solidity but when I am doing
function StringToBytes(string memory _str) public pure returns (bytes memory) {
return bytes(_str);
}
function StringToBytesLength(string memory _str) public pure returns (uint256) {
return bytes(_str).length;
}
The result of StringToBytes is giving me 42 which should ideally gives me 20. If I am trying the same thing in python i.e convert string to bytes , it is giving me 20 bytes which is the length of an ethereum address in bytes. I had found several solutions to convert address string to address type but none of them is working for solidity version 0.7.
Please help.
I want a solution but it is not optimal, I am looking for a solution which is lighter on gas fees, It is now consuming 77492.
function fromHexChar(uint8 c) public pure returns (uint8) {
if (bytes1(c) >= bytes1('0') && bytes1(c) <= bytes1('9')) {
return c - uint8(bytes1('0'));
}
if (bytes1(c) >= bytes1('a') && bytes1(c) <= bytes1('f')) {
return 10 + c - uint8(bytes1('a'));
}
if (bytes1(c) >= bytes1('A') && bytes1(c) <= bytes1('F')) {
return 10 + c - uint8(bytes1('A'));
}
return 0;
}
function hexStringToAddress(string calldata s) public pure returns (bytes memory) {
bytes memory ss = bytes(s);
require(ss.length%2 == 0); // length must be even
bytes memory r = new bytes(ss.length/2);
for (uint i=0; i<ss.length/2; ++i) {
r[i] = bytes1(fromHexChar(uint8(ss[2*i])) * 16 +
fromHexChar(uint8(ss[2*i+1])));
}
return r;
}
function toAddress(string calldata s) public pure returns (address) {
bytes memory _bytes = hexStringToAddress(s);
require(_bytes.length >= 1 + 20, "toAddress_outOfBounds");
address tempAddress;
assembly {
tempAddress := div(mload(add(add(_bytes, 0x20), 1)), 0x1000000000000000000000000)
}
return tempAddress;
}
How in solidity to set the fixed length of returned array, according to the array in parameters?
// For example I have this simple function, which convert array uint to int
// but this not works, because dynamic length array
function convertUintToInt(uint[] _input) public pure returns(int[] _output){
for(uint i = 0; i < _input.length; i++){
_output[i] = int(_input[i]);
}
return _output;
}
// this works for length 10, but if input.length < 10 this return unnecessary empty items
// if _input.length > 10 this will not works
function convertUintToInt(uint[] _input) public pure returns(int[10] _output)
// I need just something like this
function convertUintToInt(uint[] _input) public pure returns(int[_input.length] _output)
Main goal not use storage!
I just need create readable contract helper for convert data
pragma solidity ^0.5.12;
contract Ballot {
function convertUintToInt(uint256[] memory _input) public pure returns(int[] memory){
int[] memory tmpArr = new int[](_input.length);
for(uint i = 0; i < _input.length; i++){
tmpArr[i] = int(_input[i]);
}
return tmpArr;
}
}
I use remix IDE. When I call the function get number I got this 0: uint256[]:
How can I change it to return the dynamic array's numbers?
pragma solidity ^0.4.24;
contract dynamicarray {
uint public constant MaxNumber = 50;
uint[] numbers;
function randomnumber() public view returns (uint){
uint random = uint(sha3(block.timestamp)) % MaxNumber +1;
for(uint i = MaxNumber; i > numbers.length; i++){
numbers.push(random);
return random;
}
}
function getnumbers() public view returns(uint[]){
return numbers;
}
}
The function is a view, so it can't modify state. Calling randomnumber() will return a value, but it won't change the numbers array.
Drop the view modifier from randomnumber(), and it will add one item to the array. (The early return will prevent the loop from repeating.)
Try this
pragma solidity ^0.4.24;
contract dynamicarray {
uint public constant MaxNumber = 50;
uint[] numbers;
function randomnumber() public returns (uint){
uint random = uint(keccak256(block.timestamp)) % MaxNumber +1;
for(uint i = MaxNumber; i > numbers.length; i++){
numbers.push(random);
return random;
}
}
function getnumbers() public view returns(uint[]){
return numbers;
}
}
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++) {