Getting accurate gas cost after each function call - solidity

I implemented a dynamic array in solidity for my own use. The following is my implementation. I can get the accurate gas cost of each function call by clicking the debug message in the console of remix. However, manually getting gas costs is tedious and I'm thinking if I can write another solidity script to get the gas cost of my function call. For example, I want to get the gas cost of consecutively calling push API for 10000 times. The x-axis should be the number of API calls, and the y axis should be the cumulative gas cost up to i API calls. Is there any built-in function in solidity to help me do that?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract Array {
// Several ways to initialize an array
uint[] public arr;
uint[] public arr2 = [1, 2, 3];
// Fixed sized array, all elements initialize to 0
uint[10] public myFixedSizeArr;
function get(uint i) public view returns (uint) {
return arr[i];
}
// Solidity can return the entire array.
// But this function should be avoided for
// arrays that can grow indefinitely in length.
function getArr() public view returns (uint[] memory) {
return arr;
}
function push(uint i) public {
// Append to array
// This will increase the array length by 1.
arr.push(i);
}
function pop() public {
// Remove last element from array
// This will decrease the array length by 1
arr.pop();
}
function getLength() public view returns (uint) {
return arr.length;
}
function remove(uint index) public {
// Delete does not change the array length.
// It resets the value at index to it's default value,
// in this case 0
delete arr[index];
}
function examples() external {
// create array in memory, only fixed size can be created
uint[] memory a = new uint[](5);
}
}

You can use msg.gas and store the value to a variable, when the contract is executed the gas amount will be stored.

Related

Does the order of memory arguments in the Solidity function matter?

i'm trying to make the simple storage using Solidity. Here I'm just trying to map name to some number.
The problem is the following: if I use store_first() it does not work (the retrieve() function returns 0 in any case). But if I change the order of the arguments and place the string memory _name before uint256 _favoriteNumber everything works (the retrieve() function returns correct number)
Does the problem relates to the order (if yes, why?) or I missed something else?
// SPDX-License-Identifier: MIT
pragma solidity >0.6.0;
contract SimpleStorage {
mapping(string => uint256) public nameToNumber;
// If i use this function, the retrieve function always returns 0
function store_first(uint256 _favoriteNumber, string memory _name) public {
nameToNumber[_name] = _favoriteNumber;
}
// If i use this function, the retrieve function returns correct number
function store_second(string memory _name, uint256 _favoriteNumber) public {
nameToNumber[_name] = _favoriteNumber;
}
function retrieve(string memory _name) public view returns(uint256){
return nameToNumber[_name];
}
}

I keep on getting ParseError: Expected type name // when I want to return a struct I have just created

I am new in Solidity and I have been trying to create and get STRUCT without adding it to an Array. I alway see Structs with arrays and the method .push and I wanted to try it without it.
I have created a single Contract with one Struct and one function to create and get it.
If I create a single public function to create, but not return, the struct it doesn´t give me any error... Like the following:
struct Todo {
string name;
uint age;
}
function createTodo(string memory _name, uint _age) public pure{
Todo memory myTodo = Todo(_name, _age);
}
With the above code I would also like to know why it wouldn´t let me set the pointer "Todo" as storage like: Todo storage myTodo = Todo(_name, _age); It gives an TypeError: Todo memory is not implicity convertible to expect type struct storage pointer.
Next, I tried to modify the function to create and RETURN but then is when I start getting the ParseError.
The code is the following:
function getTodo(string memory _name, uint _age) public returns(struct myTodo) {
Todo memory myTodo = Todo(_name, _age);
return myTodo;
}
With the aobve code I also tried in "returns(struct), returns(struct memory)"....
I would really appreciate any type of help here.
Thank you very much
You received this error because you're wrong to set a returns keyword on getTodo() function. In your case, you must change your function in this way:
function getTodo(string memory _name, uint _age) external pure returns(Todo memory) {
Todo memory myTodo = Todo(_name, _age);
return myTodo;
}
If you want to handle storage structs, see this smart contract code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Test {
struct Todo {
string name;
uint age;
}
// Declare state variable
Todo[] todoArray;
// Push into array new struct
function createTodo(string memory _name, uint _age) public {
todoArray.push(Todo(_name, _age));
}
// Retrieve ToDo struct from specific index about struct array
function getTodo(uint _index) external view returns(Todo memory) {
return todoArray[_index];
}
}

Iteract with arrays from another contract

Does anyone know how can I read meanings of variables in the array from another contract ? For example:
pragma solidity 0.8.7;
contract Contract1{
uint[] newData ;
constructor(uint _i){
newData.push(_i);
}
}
interface IContract1 {
function newData() external returns(uint[] memory);
}
contract Contract2 {
uint public newOne;
function foo(address _addr, uint _i) external{
newOne = IContract1(_addr).newData()[_i];
}
}
This code has compiled success in the Remix, but I have an error when I trying call foo()
Contract1.newData is an internal (default visibility when you don't specify it) property.
But the interface IContract1 defines an external function named newData() (without the index argument).
You can modify the newData property to have a public visibility, for which the compiler autogenerates a getter function (with the index argument).
Then you also need to update the function definition in the interface, so that it contains the index argument and returns just one item (and not the whole array).
pragma solidity ^0.8;
contract Contract1 {
// changed visibility to `public`
uint[] public newData;
constructor(uint _i){
newData.push(_i);
}
}
interface IContract1 {
// added `_index` argument
// changed the return value to one item of the array
function newData(uint256 _index) external returns(uint);
}
contract Contract2 {
uint public newOne;
function foo(address _addr, uint _i) external{
// changed the call to the getter function
// instead of trying to access the property directly
newOne = IContract1(_addr).newData(_i);
}
}
Note that the Contract1 constructor pushes the first item to the array, so you need to pass 0 (as for the first index) to the foo() function argument uint _i.
Repro steps:
Deploy Contract1 passing it 123 as constructor param. Deployed to address 0x456.
Deploy Contract2
Execute Contract2 function foo(0x456, 0), which will effectively set Contract2.newOne value to 123.

How to push onto a dynamic sized Array within a function with Solidity?

How can I push a value into an dynamic sized array within a function?
I have a function which builds an array dynamically to use this as a function argument afterwards:
function autoMintBatch(...) {
uint32[] xList;
uint32[] yList;
// ... y is declared properly ...
yList.push(y);
for (uint256 i = 0; i < idList.length; i++) {
xList.push(x++);
}
}
I get the following compilation error:
TypeError: Member "push" is not available in uint32[] memory outside
of storage.
But when I change the variable declaration to storage like:
uint32[] storage xList;
another error appears:
TypeError: This variable is of storage pointer type and can be
accessed without prior assignment, which would lead to undefined
behaviour.
Is there any way to build an array dynamically within a function?
Assign the result of "x++" in a variable inside the function and then try to push the variable inside the array. Remember to create a state variable for the array. This worked for me
Item[] public items;
event MarketItem(
bytes32 title,
uint8 price,
bool sold,
bool published,
address owner
);
mapping(address => Item) public itemToOwner;
function addItem(bytes32 _title, uint8 _price) public {
Item memory newItem = Item({
title: _title,
price: _price,
sold: false,
published: true,
owner: msg.sender
});
items.push(newItem);
}
Only dynamic storage arrays can be resized (push/pop).
In your case better implementation could rely on static memory array with fixed size, such as:
function autoMintBatch(...) public virtual returns (uint256[] memory)
{
...
uint256[] memory xList = new uint[](idList.length);
for(uint256 i = 0; i< amount ; i++)
{
xList[i] = y++;
}
return xList;
}

How to return the Entered Value from Mapping Corresponds to address[msg.sender]

I am hitting hard to creating a lottery smart contract in solidity. I have tried a couple of ways, first I stored all the players address inside an array, but unfortunately that logic fail, just because of slow execution of array (when entries are more 1000+).
Now I am trying mapping mapping(address => Struct) entries;. Now what I have done here. I created a structure with user first ticket number and user last ticket number i.e uint userFstTcktNumber;
uint userLstTcktNumber;
Here is my structure
struct UserInfo {
uint userFstTcktNumber;
uint userLstTcktNumber;
} UserInfo userinfo;
Then I created a mapping
mapping(address => UserInfo ) public entry;
Then I have Created a function to enter the values inside the mapping and structure.
function letsdo(uint first, uint last) public{
entry[msg.sender];
userinfo.userLstTcktNumber = first;
userinfo.userLstTcktNumber = last;
}
Now what I want to do? I just want to get the values from the mapping and structure corresponding to the address, let's say I have 10 entries from 1 to 10 from address "0x617F2E2fD72FD9D5503197092aC168c91465E7f2" . And I have another 50 entries from 11 to 51 from another address "0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C".
To return this I am using the function
function get(address) public view returns(uint, uint){
return (userinfo.userFstTcktNumber, userinfo.userLstTcktNumber);
}
But it's not returning me the expected result.
It's always returning the userFstTcktNumber is 0, no matter what address I have passed inside the get().
What's wrong with this code?
You are not really using your map, you need to set the values to be able to search inside it.
function letsdo(uint first, uint last) public {
entry[msg.sender] = UserInfo(first, last);
}
You don't need a get function as well, since entry is already public, you can search directly using entry[<address>]
UserInfo userinfo after your struct is also unnecessary, since you want to work with map, you will need more than just an instance, the letsdo function I mentioned above is already doing it
Hey thanks everyone for helping me out, Actually Last night I sorted it out my own. And here is the full logic for the problem.
pragma solidity ^0.4.18;
contract lottery{
uint public lastTicketNumber = 0;
uint youEntredWithAmount;
address [] public players;
uint public entryFee = 0.01 ether;
struct UserInfo {
uint userFstTcktNumber;
uint userLstTcktNumber;
}
mapping(address => UserInfo ) public entry;
function letsdo(uint first, uint last) public{
players.push(msg.sender);
entry[msg.sender].userFstTcktNumber = first;
entry[msg.sender].userLstTcktNumber = last;
}
function currentLevel(address userAddress) public constant returns (uint, uint) {
return (entry[userAddress].userFstTcktNumber, entry[userAddress].userLstTcktNumber);
}
function numberOfParticipents() public view returns(address [] memory){
return players;
}
}