I am unable to retrieve values on this code.
//SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.1;
contract Storage{
int number;
function storePositive(int256 nump) public{
number = nump;
}
function storeNegative(int256 numn) public{
number = -numn;
}
function retreivep() public view returns(int256){
return number;
}
function retreiven() public view returns(int256){
return number;
}
}
I am trying to retrieve separate values for positive and negative numbers stored. All it is showing me is
0:int256: 0 on both retrievep and retrieven.
P.S. This is my first ever Solidity code, so please explain on an elementary level.
Related
pragma solidity ^0.8.0;
contract Counter {
uint public number;
string public name;
constructor(string memory input_name, uint input_number){
name = input_name;
number = input_number;
}
function add () public {
number ++;
}
function subtract() public {
number --;
}
function update_name(string memory update) public {
name = update;
}
I wrote a very basic contract here and I'm wondering why I should write a return statement for each of my functions as it is already returns a value.
Could someone explain my error or the point of the return statement here?
Solidity have the "implicit return" feature, so as you noticed, you may skip the "return" statement in some cases. However, it's discourages, since you're not explicit enough and may cause a lot of confusion and issues.
For details please check the following links:
https://medium.com/#pareshmasani/ethereum-smart-contract-implicit-return-can-go-wrong-33b41c93dbba
https://github.com/ethereum/solidity/issues/3134
https://blog.openzeppelin.com/instadapp-audit/
I'm using web3j in Android studio to interact with smartcontracts.
In my SmartContract i've 2 functions getName() and getAge() and i'm setting age and name in constructor as below:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;
contract Identify {
string name;
uint age;
constructor() public {
name = "Shoaib Khalid";
age = 22;
}
function getName() view public returns(string memory){
return name;
}
function getAge() view public returns(uint){
return age;
}
}
But I'm not able to read the value returned by both functions. After deploying the smartcontract correctly, following is the method I'm trying to read the value returned by getName() function.
val identityContract = Identity_sol_Identify.load(
deployedContractAddress,
web3j,
getCredentialsFromPrivateKey(),
DefaultGasProvider.GAS_PRICE,
DefaultGasProvider.GAS_LIMIT
)
Log.d(TAG, "counter Result: ${identityContract.name.sendAsync().get()}")
Instead of getting the value Shoaib Khalid which I set in the constructor I'm getting a TranscriptReciept object the output screenshoot is attached below.
So I want to know can you read the exact value returned by the function getName() in smartcontract using web3j?
Please refer to the Web3j documentation:
Transactional calls do not return any values, regardless of the return type specified on the method. Hence, for all transactional
methods the Transaction Receipt associated with the transaction is
returned [1]
...
The transaction receipt is useful for two reasons:
It provides details of the mined block that the transaction resides in Solidity events that are called will be logged as part of
the transaction, which can then be extracted.
You are getting the transaction receipt. In order to query the values from your state variables you should refer to the section Querying the state of a smart contract and do something like this:
Function function = new Function<>(
"getName", // This is the name of the solidity function in your smart contract
Collections.emptyList(), // Solidity Types in smart contract functions, no input in the function so we set this to empty
Arrays.asList(new TypeReference<Utf8String>() {})); // result will be a string
String encodedFunction = FunctionEncoder.encode(function);
org.web3j.protocol.core.methods.response.EthCall response = web3j.ethCall(
Transaction.createEthCallTransaction(contractAddress, encodedFunction),
DefaultBlockParameterName.LATEST)
.sendAsync().get();
Iterator<Type> it = someType.iterator();
Type result = someType.get(0);
String a = result.toString();
Log.d("Name: ", a);
I've a smartcontract in which I've a function getLevels() that returns an array of struct type MLevel, defined at the beginning of smartcontract.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
struct MLevel{
address id;
string levelPrize;
uint levelNo;
uint levelCriteria;
}
contract Test{
MLevel[] public mlevels;
function addLevel(uint _levelCriteria, string memory _levelPrize)public payable{
MLevel memory level;
level.id = msg.sender;
level.levelCriteria = _levelCriteria;
level.levelPrize = _levelPrize;
mlevels.push(level);
}
function getLevels() public view returns(MLevel [] memory){
return mlevels;
}
}
The above smartcontract works absolutely fine in Remix ide. But when I try to create its java wrapper class using web3j, wrapper class does not generate and web3j ends with a weird error part 'struct MLevel' is keyword as shown below in the image
I am learning Ethereum dev in Solidity and trying to run a simple HelloWorld program but ran into the following error:
Data location must be "memory" or "calldata" for return parameter in function, but none was given.
My code:
pragma solidity ^0.8.5;
contract HelloWorld {
string private helloMessage = "Hello world";
function getHelloMessage() public view returns (string){
return helloMessage;
}
}
You need to return string memory instead of string.
Example:
function getHelloMessage() public view returns (string memory) {
return helloMessage;
}
The memory keyword is the variable data location.
For those reading this who have similar code, 'memory' may not necessarily be the correct word to use for you. You may need to use the words 'calldata' or 'storage' instead. Here is an explanation:
Memory, calldata (and storage) refer to how Solidity variables store values.
For example:
1. Memory: here is an example using the word 'memory':
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import 'hardhat/console.sol'; // to use console.log
contract MemoryExample {
uint[] public values;
function doSomething() public
{
values.push(5);
values.push(10);
console.log(values[0]); // logged as: 5
modifyArray(values);
}
function modifyArray(uint[] memory arrayToModify) pure private {
arrayToModify[0] = 8888;
console.log(arrayToModify[0]) // logged as: 8888
console.log(values[0]) // logged as: 5 (unchanged)
}
}
Notice how the 'values' array was not changed in the private function because 'arrayToModify' is a copy of the array and does not reference (or point to the array that was passed in to the private function.
2. Calldata is different and can be used to pass a variable as read-only:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract CallDataExample {
uint[] public values;
function doSomething() public
{
values.push(5);
values.push(10);
modifyArray(values);
}
function modifyArray(uint[] calldata arrayToModify) pure private {
arrayToModify[0] = 8888; // you will get an error saying the array is read only
}
}
3. Storage: a third option here is to use the 'storage' keyword:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import 'hardhat/console.sol'; // to use console.log
contract MemoryExample {
uint[] public values;
function doSomething() public
{
values.push(5);
values.push(10);
console.log(values[0]); // logged as: 5
modifyArray(values);
}
function modifyArray(uint[] storage arrayToModify) private {
arrayToModify[0] = 8888;
console.log(arrayToModify[0]) // logged as: 8888
console.log(values[0]) // logged as: 8888 (modifed)
}
}
Notice how by using the memory keyword, the arrayToModify variable references the array that was passed in and modifies it.
use string memory instead of string.
storage - variable is a state variable (store on blockchain)
memory - variable
List item - is in memory and it exists while a function is being called
calldata - special data location that contains function arguments, only available for external functions
example code : Data Locations
This is my contract code. Here I'm trying to store the coordinates of a particular trip. While storing the information contract executing fine. But When I retrieve the data, It should give the array of coordinates. But it is throwing an error.
reason: 'insufficient data for uint256 type'
contract TripHistory {
struct Trip {
string lat;
string lon;
}
mapping(string => Trip[]) trips;
function getTrip(string _trip_id) public view returns (Trip[]) {
return trips[_trip_id];
}
function storeTrip(string _trip_id, string _lat, string _lon) public {
trips[_trip_id].push(Trip(_lat, _lon));
}
}
What I'm missing here. Is there any other way to achieve what I'm trying here?
P.S: I'm new to solidity.
First of returning structs is not supported in Solidity directly. Instead you need to return every individual element in the struct as below.
Function xyz(uint256 _value) returns(uint256 User.x, uint256 User.y)
public {}
But then there’s an experimental feature that will help you with returning struct. All that you need to do is add the following after your first pragma line
pragma experimental ABIEncoderV2;
then continue with your code. That should work with no changes to your code.
An example of abiencoderv2 returning struct can be found at this link
It is not possible in solidity to return struct array.
As jlo said in this link, after version 0.8.0, it is possible to return a struct. jlo describes how to set and return an element of array of struct. Here I describe how to set, reset, and return a struct type variable.
I tested it and my test environment is:
private Ethereum network
Geth version 1.10.9-stable (for private network)
Slocjs Compiler version 0.8.7
web3js version 1.5.1
Note, you have to first define the struct type outside of any function inside the contract.
A supper intuitive example code is as follows:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract testContract {
struct funcResultType {
uint[] var1;
string[] var2;
string message;
}
funcResultType private funcResult;
function testSetFunc(string memory inputVar) public payable {
funcResult.var1.push(123);
funcResult.var2.push(inputVar);
funcResult.message = "Done!";
}
function testResetFunc() public payable {
delete funcResult; // reset variales
}
function testGetFunc() public view returns (funcResultType memory){
return funcResult;
}
}
The result of the test with Web3js in the console is as follow:
As you can see the whole variables are accessible. I upload its web3js code in Github in this link.