CompilerError: Stack too deep, try removing local variables - stack

I am trying to do a dapp project.
I have an error about stack too deep, but I don't know how can I solve this problem.
CompilerError: Stack too deep, try removing local variables.
--> contracts/proje.sol:145:5:
|
145 | function addRecord(address _addr, s ... gedOn, string memory ipfs) public {
| ^ (Relevant source part starts here and spans across multiple lines).
And actually, struct will consist of more data than there is. If this gives an error in the number of data, what do we do when we want to enter too much data?
contract Patient is Clinic {
uint256 public p_index = 0;
struct Records {
string cname;
string l_cadence;
string r_cadence;
string n_cadence;
string l_dsupport;
string r_dsupport;
string n_dsupport;
string l_footoff;
string r_footoff;
string n_footoff;
string l_steptime;
string r_steptime;
string n_steptime;
string admittedOn;
string dischargedOn;
string ipfs;
}
struct patient {
uint256 id;
string name;
string phone;
string gender;
string dob;
string bloodgroup;
string allergies;
Records[] records;
address addr;
}
address[] private patientList;
mapping(address => mapping(address=>bool)) isAuth;
mapping(address=>patient) patients;
mapping(address=>bool) isPatient;
function addRecord(address _addr, string memory cname, string memory l_cadence, string memory r_cadence, string memory n_cadence, string memory l_dsupport, string memory r_dsupport, string memory n_dsupport, string memory l_footoff, string memory r_footoff, string memory n_footoff, string memory l_steptime, string memory r_steptime, string memory n_steptime, string memory admittedOn, string memory dischargedOn, string memory ipfs) public {
}
}

Compiler error is for parameters number about addRecord() function.
To solve this problem, you can use directly Records struct in this way:
function addRecord(address _addr, Records memory record) public {
// your logic
}
Another options to solve this problem is to change type function from public to internal, like:
function addRecord(address _addr, string memory cname, string memory l_cadence, string memory r_cadence, string memory n_cadence, string memory l_dsupport,
string memory r_dsupport, string memory n_dsupport, string memory l_footoff, string memory r_footoff, string memory n_footoff, string memory l_steptime,
string memory r_steptime, string memory n_steptime, string memory admittedOn, string memory dischargedOn, string memory ipfs) internal {
// your logic
}
NOTE: Before to do this modify, see the difference between public and internal types function here.

Related

Can I use `objectId()` from `mongo_dart` to create a unique string?

I am finding a solution to create a unique string to create a file name. I realized that the ObjectId() has an id.$oid that is a unique string. But I am not sure. Is it work success full with this?
example code:
List<FileObject> generateFileName(List<FileObject> files) {
return files.map((e) => e..updateName(ObjectId().$oid)).toList();
}
class FileObject {
FileObject({this.name, this.path, this.url, this.type});
String? name;
String? path;
String? url;
String? type;
void updateName(String? name) => this.name = name;
}
Is the ObjectId().$oid working perfectly?
Is there a better way?
An ObjectId should be unique as it is a 12-byte BSON type hexadecimal string that includes randomization based on the time its created.
Source/reference: https://www.knowledgehut.com/blog/web-development/objectid-in-mongodb

why do I need to use a late modifier here?

class Car {
String model;
String brand;
String _engine;
static int carProduced = 0;
Car(String model, String brand, String engine) {
this._engine = engine;
this.brand = brand;
this.model = model;
}
}
I am getting this error.
Non-nullable instance field '_engine' must be initialized.
Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'.
I am not actually sure. As I am initializing that non-nullable field in the default constructor why do I need to use a late modifier here?
String model = "";
String brand = "";
String _engine = "";
Adding initializer expression solved the error.
Does it mean that object fields are created even before the constructor call ??
Dart objects are created in two steps/phases:
Initialization of values.
Execution of constructor body.
So all non-nullable non-late values must have a value before we executes the constructor body. The reason is that inside the constructor body we are allowed to use all values inside the object.
We can therefore in Dart run initialization code before running the constructor body like:
class Car {
String model;
String brand;
String _engine;
static int carProduced = 0;
Car(String model, String brand, String engine)
: this.model = model,
this.brand = brand,
this._engine = engine;
}
But since this is kinda redundant we have the follow shortcut to do the same:
class Car {
String model;
String brand;
String _engine;
static int carProduced = 0;
Car(this.model, this.brand, this._engine);
}

Solidity - ParserError: Expected primary expression when using var

I am trying to create a struct and add mapping in such a way that it can be retrieved later on using its address using the below code.
pragma solidity ^0.8.0;
contract Courses {
struct Instructor {
uint age;
string fName;
string lName;
}
mapping (address => Instructor) instructors;
address[] public instructorAccts;
function setInstructor(address _address, uint _age, string _fName, string _lName) public {
var instructor = instructors[_address]; //ERROR HERE
instructor.age = _age;
instructor.fName = _fName;
instructor.lName = _lName;
instructorAccts.push(_address) -1;
}
}
However, I am getting an error at the line var instructor = instructors[_address]
The error is ParserError: Expected primary expression
I am unable to understand what the issue is and how to resolve it. Could anyone help with this?
Solidity uses typed variables, doesn't have the generic var keyword (that is used in JavaScript for example).
When declaring reference types (in your case string and struct), you need to specify their data location - in your case memory for the string argument. And either memory or storage for the struct depending on whether you want to set the values just in the context of the setInstructor() function (location memory), or if you want to set its values in the contract storage (location storage).
function setInstructor(address _address, uint _age, string memory _fName, string memory _lName) public {
// either `memory` or `storage` depending on your use case
Instructor storage instructor = instructors[_address];
// ... rest of your code
There also is a syntax error on this line
instructorAccts.push(_address) -1;
you can fix it by removing the -1
instructorAccts.push(_address);

Is there a type for dictionary in Dart?

I'm trying to get a request from this link: https://cms.paladins.com/wp-json/wp/v2/champions?slug=dredge&lang_id=1 and transform a class in dart by:
https://javiercbk.github.io/json_to_dart/
But the problem is: the site is generating some strange code that i cant understand:
In inspect of chrome i have:
api_information {
Ability1: "Cursed Howitzer"
Ability2: "Broadside"
Ability3: "Harpoon"
Ability4: "Shortcut"
Ability5: "Kraken"
AbilityId1: 23600
AbilityId2: 23611
AbilityId3: 23612
AbilityId4: 23622
AbilityId5: 23613
Ability_1: {,…}
Ability_2: {,…}
Ability_3: {,…}
Ability_4: {,…}
Ability_5: {,…}
....
But when i translate to Dart:
class ApiInformation {
String ability1;
String ability2;
String ability3;
String ability4;
String ability5;
int abilityId1;
int abilityId2;
int abilityId3;
int abilityId4;
int abilityId5;
Ability1 ability1;
Ability1 ability2;
Ability1 ability3;
Ability1 ability4;
Ability1 ability5;
....
I get the int and the string, but why he create a new Class for every dictionary? Is there a type for dictionary in Dart? And why he rename ability_1 to ability1 is there a pattern in Dart about underscore?
There's a limit when using code generators : they don't know the intention behind the json payload and are unable to make the right decisions when facing complex structures.
In other owrds, don't use them !
The equivalent of a Dictionnary in Dart is a Map. In your case, probably something like a Map<String, Ability> with:
class Ability {
String description;
int id;
String summary;
String uRL;
String damageType;
int rechargeSeconds;
...
}

How to ignore "too many parameters" on constructors that use injection

If you are using dependency injection it's totally normal that constructors have many parameters.
Is it possible that sonarlint doesn't show the "too many parameters" code smell warning for constructors that use injection?
In my case a Spring service needed a lot of other services in order to do its work. So rule squid:S00107 fired and gave me an error in the SonarCube. I found this article which proposed to use Lombok to work around the issue like so:
Before:
#Component
public class EventService {
private final String param1;
private final String param2;
private final String param3;
private final String param4;
private final String param5;
private final String param6;
private final String param7;
private final String param8;
private final String param9;
public EventService(String param1, String param2, String param3, String param4, String param5, String param6, String param7, String param8, String param9) {
this.param1 = param1;
this.param2 = param2;
this.param3 = param3;
this.param4 = param4;
this.param5 = param5;
this.param6 = param6;
this.param7 = param7;
this.param8 = param8;
this.param9 = param9;
}
...
After:
#Component
#RequiredArgsConstructor
public class EventService {
private final String param1;
private final String param2;
private final String param3;
private final String param4;
private final String param5;
private final String param6;
private final String param7;
private final String param8;
private final String param9;
...
As other posters noted before, too many arguments for a method or constructor show that somehow the separation of concerns principle has been violated. It is better to go with the following solutions:
in case of a constructor: a builder pattern
in case of a method: with a request parameter and a builder if has too many parameters.
This avoids confusion of parameters, i.e. "Was the x, y or the z first argument?"
If all tries fail annotate #SuppressWarnings("squid:S00107") on top of the method / constructor you want to ignore. This can only be last resource.

Resources