I try to compile a smart contract using Truffle framework and I get following output:
Compiling ./contracts/PartProduction.sol...
InternalCompilerError: Stack too deep, try using fewer variables.
Compilation failed. See above.
Truffle v5.0.1 (core: 5.0.1)
Node v11.6.0
The source code of the smart contract written with Solidity 0.5.0 is:
pragma solidity 0.5.0;
contract PartProduction {
enum State {
productionRequested,
parametersObtained,
manufacturerObtained,
productionForwardedToManufacturer,
printing,
printed,
postProcessing,
postProcessed,
qualityChecking,
qualityChecked,
productionFinished
}
enum Priority {
low,
normal,
high
}
struct Company {
address vehicleEthAddress;
address myWebService;
}
struct Manufacturer {
string id;
string location;
address productionMachine1;
address productionMachine2;
address productionMachine3;
}
struct Production {
string productionParameters;
string designParameters;
State state;
Priority priority;
string partNumber;
uint256 cost;
uint256 productionForwardedTime;
uint256 productionStartTime;
uint256 productionEndTime;
address partID;
string myIdentifier;
string location;
}
Company public company;
Manufacturer public manufacturer;
Production public production;
constructor(
address _vehicleEthAddress,
string memory _myIdentifier,
string memory _vehicleLocation,
string memory _partNumber,
Priority _priority)internal {
company.myWebService = msg.sender;
company.vehicleEthAddress = _vehicleEthAddress;
production.partID = address(this);
production.state = State.productionRequested;
production.partNumber = _partNumber;
production.priority = _priority;
production.myIdentifier = _myIdentifier;
production.location = _vehicleLocation;
}
function setParameters(string calldata _designParametersHash, string calldata _productionParametersHash) external {
require(msg.sender == company.myWebService);
require(production.state == State.productionRequested);
production.designParameters = _designParametersHash;
production.productionParameters = _productionParametersHash;
production.state = State.parametersObtained;
}
function setManufacturer(string calldata _manufacturerId, string calldata _manufacturerLocation) external {
require(msg.sender == company.myWebService);
require(production.state == State.parametersObtained);
manufacturer.id = _manufacturerId;
manufacturer.location = _manufacturerLocation;
production.state = State.manufacturerObtained;
}
function forwardProductionData(uint256 _productionForwardedTime) external {
require(msg.sender == company.myWebService);
require(production.state == State.manufacturerObtained);
production.state = State.manufacturerObtained;
production.productionForwardedTime = _productionForwardedTime;
}
function registerproductionMachine1(address _productionMachine1) external {
require(msg.sender == company.myWebService);
manufacturer.productionMachine1 = _productionMachine1;
}
}
I would like to know if there is a way to understand and identify the part where the number of variables exceeds. Should I turn everything into a mapping? The compiler does not provide me with further information.
Also, I found this question, it's similar, but I'm not sure it's the same problem, a cons it is to save the variables in memory (memory keyword) when you do a get, another is to set them. Is the use of mapping the only possible alternative to tackle this problem? Furthermore, the smart contract is not concluded, many other parts will be added later.
As far as I can see, your stack is too deep for the struct production, you can use a trick here to solve this issue, create a separate smart contract with the name Production, define the structure there and import the contract in this smart contract. This will help you in both reducing your gas consumption while deploying the contract and this stack too deep issue.
This you can do for other structs as well if you wish. The only thing you need to take care of is the mapping while you implement for mapping the structure to a particular contract. As for each contact it will be counted as separate map.
Let me know if you need any further assistance. I want you to try out this solution hopefully, this will work.
Related
so, First, I imported the simpleStorage contract and then wrote this function createNeewContracts() to push the contract address into an array
everything was going smooth and I got an idea
"why not just use a struct of two variables 1. string (name of the contract owner) and 2. address (of the contract the owner owns) and i can then have name of owner and his contract as a struct stored in an array named contractAndThereArray"
I could have used mapping but I used struct and array to do the work
I ran into a problem it say
"TypeError: Invalid type for argument in function call. Invalid implicit conversion from contract SimpleStorage1 to address requested."
here is the code:-
contract StorageFactory{
// SimpleStorage public simpleStorage;
struct ownerAndThereContracts {
string name;
address nf;
}
ownerAndThereContracts[] public saveYourContracts;
SimpleStorage1[] public x;
// mapping(string => address) y;
uint256 counter;
function createNewContracts() public {
SimpleStorage1 simpleStorage = new SimpleStorage1();
x.push(simpleStorage);
// address j = simpleStorage;
}
function refering(string memory _name) public {
counter++;
SimpleStorage1 simpleStorage2 = SimpleStorage1(x[counter]);
saveYourContracts.push(ownerAndThereContracts(_name,simpleStorage2)); // the error occurs here it says simpleStorage2 is not address but contract
}
}
The problem is with the function referring where i tried to refer the address of a contract with the owners name but seems there is a problem
Please,if someone can explain it. Please explain I need your help guys
i've been tried to solve it for hours now but nothing seems to fit
I tried to get into your logic and fixed your contract and solve your mistake. Specifically, your error states that you cannot insert an instance of a contract into a field with datatype address. In order to solve this problem you need to cast the contract instance in address datatype. You can see the contract in the following lines, I have also inserted some notes to let you understand what I have changed:
// SDPX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "./SimpleStorage1.sol";
contract StorageFactory{
uint256 counter;
struct ownerAndThereContracts{
string name;
address nf; // NOTE: I assume that it's the SimpleStorage address
}
ownerAndThereContracts[] public saveYourContracts;
SimpleStorage1[] public x;
function createNewContracts() public {
SimpleStorage1 simpleStorage = new SimpleStorage1();
x.push(simpleStorage);
}
function refering(string memory _name) public {
// NOTE: I assume that when creating new contract, then you must refering it directly to an owner.
// In this case, I retrieve the length of array in details the last element index.
counter = x.length-1;
SimpleStorage1 simpleStorage2 = SimpleStorage1(x[counter]);
// NOTE: You must cast your contract instance to an address for put it into your struct (because the datatype is 'address')
saveYourContracts.push(ownerAndThereContracts(_name,address(simpleStorage2)));
}
}
Ok first i fixed your code, you are missing 2 casting, first to address and then to a paybale address.
Here:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;
contract SimpleStorage1{
}
contract StorageFactory{
// SimpleStorage public simpleStorage;
struct ownerAndThereContracts {
string name;
address nf;
}
ownerAndThereContracts[] public saveYourContracts;
SimpleStorage1[] public x;
// mapping(string => address) y;
uint256 counter;
function createNewContracts() public {
SimpleStorage1 simpleStorage = new SimpleStorage1();
x.push(simpleStorage);
// address j = simpleStorage;
}
function refering(string memory _name) public {
counter++;
SimpleStorage1 simpleStorage2 = SimpleStorage1(x[counter]);
address simpleStorage2Address = address(simpleStorage2); //first cast to address
address payable _finalCast = payable(simpleStorage2Address); // then cast to payable address
saveYourContracts.push(ownerAndThereContracts(_name, _finalCast));
}
But you should know that this is a very costy contract, you should take out all the process of saving the contract to a environment like c or java and only create the contract through solidity so the objects on memory wont cost you.
Anyway good luck!
From docs: contract-types
Explicit conversion to and from the address payable type is only
possible if the contract type has a receive or payable fallback
function. The conversion is still performed using address(x). If the
contract type does not have a receive or payable fallback function,
the conversion to address payable can be done using
payable(address(x))
I explained here contract-type vs address type
In Solidity a contract variable is really just an address under the
hood.
I have been written a smart contract, I am trying to execute the following code but I have these problems:
1- "Gas requirement of function EKM.register_PK is infinite: If the gas requirement of a function is higher than the block gas limit, it cannot be executed. Please avoid loops in your functions or actions that modify large areas of storage (this includes clearing or copying arrays in storage)
Pos: 32:0:"
2- "Use "assert(x)" if you never ever want x to be false, not in any circumstance (apart from a bug in your code). Use "require(x)" if x can be false, due to e.g. invalid input or a failing external component.
more
Pos: 30:2:"
My code:
pragma solidity >=0.8.13;
//SPDX-License-Identifier:MIT
contract EKM{
/**
* #dev VTA is a state variable
*/
address public VTA;
/**
* #dev mapping address as key to struct user with mapping name users
*/
mapping (uint => user) public users;
/**
* #dev assigning the contract deployer as the VTA
*/
constructor() {
VTA =msg.sender;
}
struct user {
string PKname;
string PKvehicle;
uint256 vP;
bool status;
}
event addPK(string name, string PKv, uint256 VPv) ;
function register_PK(uint ID_v, string memory PKname, string memory PKvehicle, uint256 vP) public returns(bool){
require(users[ID_v].status == true,"register the public key of the user");
if(msg.sender != VTA)
{revert();}
if(ID_v == 0)
{return false;}
else
{
ID_v++;
users[ID_v]= user(PKname,PKvehicle,vP,true);
//PKname=users[ID_v].PKname;
//PKvehicle=users[ID_v].PKvehicle;
// vP=users[ID_v].vP;
emit addPK(PKname, PKvehicle, vP);
return true;
}
}
}
what should I do?
Go to solidity static analysis ,and then gas and economy , untick all options except. This on local calls:
Invocation of local functions via 'this' and Delete dynamic array:
Use require/assert to ensure complete deletion. it will work
Hi guys i'm new at Solidity development, I'm currently learning and reading a project called SporesToken https://github.com/Spores-Labs/spores-token-contracts/blob/master/contracts/SporesToken.sol
And i have a question about some kind of implementation
import "#openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "./UsingLiquidityProtectionService.sol";
contract SporesToken is
UsingLiquidityProtectionService(0xBA2bF7693E0903B373077ace7b002Bd925913df2),
ERC20PresetMinterPauser,
Ownable
From where comes the hash provided to UsingLiquidityProtectionService?
Maybe this is a noob question but i didn't get it..
Part of the content of ./UsingLiquidityProtectionService.sol
import "./external/UniswapV2Library.sol";
import "./external/UniswapV3Library.sol";
import "./IPLPS.sol";
abstract contract UsingLiquidityProtectionService {
bool private unProtected = false;
IPLPS private plps;
uint64 internal constant HUNDRED_PERCENT = 1e18;
bytes32 internal constant UNISWAP =
0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f;
bytes32 internal constant PANCAKESWAP =
0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5;
bytes32 internal constant QUICKSWAP =
0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f;
enum UniswapVersion {
V2,
V3
}
enum UniswapV3Fees {
_005, // 0.05%
_03, // 0.3%
_1 // 1%
}
modifier onlyProtectionAdmin() {
protectionAdminCheck();
_;
}
constructor(address _plps) {
plps = IPLPS(_plps);
}
function LiquidityProtection_setLiquidityProtectionService(IPLPS _plps)
external
onlyProtectionAdmin()
{
plps = _plps;
}
I hope anyone here can answer me,
Kind Regards and thank you for your time.
From where comes the hash provided to UsingLiquidityProtectionService?
The hash is a smart contract address passed to the UsingLiquidityProtectionService constructor (link).
From the context I can see it's this contract on the Ethereum network. However, the contract authors didn't chose to verify the source code. So it's not possible to see the actual implementation without trying to decompile the bytecode. Just that the UsingLiquidityProtectionService expects the 0xBA2b... contract to implement the IPLPS interface.
I have a problem related to refund the users entered inside the solidity contract. I don't, have any idea if is possible iterate all the players of my contract and refund all of them with all the balance.I read in some tutorials, iterate inside the solidity contract cost a lot of gas depends of the numer of iterations.
contract Lottery{
address payable public manager;
string public name; // short name (up to 32 bytes)
address [] players;
uint256 nTickets;
address winner;
bool enable;
uint256 minimunContribution;
mapping(address => uint) public balances;
constructor (string memory LotteryName, uint minimun, address payable creator) public {
manager = creator;
name = LotteryName;
winner = address(0);
enable = true;
minimunContribution = minimun;
}
modifier restricted() {
require(msg.sender == manager, "Access forbidden");
_;
}
function enterInToLottery() public payable {
require(msg.value > minimunContribution && enable == true, "Insufficient funds to allow transfer");
players.push(msg.sender);
balances[msg.sender] += msg.value;
nTickets++;
}
//this function refund
function paybackEther(bool newfinished) public restricted {
enable = !newfinished;
selfdestruct(msg.sender);
}}
Thanks in advance to all.
Yes that can be problematic as it will use a lot of gas and may even hit limits. To solve this it is better to allow the users to withdraw the balance themselves, so they pay for the gas. Or in fact you can allow anybody to make that call. So you can offer a call refund(account:uint256) which transfers the balance (if any) to given account. Note that this would not be using msg.sender, so that anybody (including the admin) can do this transfer.
Keep in mind they need to know that they have a balance, so make sure you're emitting an event or similar. Also provide a balanceOf(address) call so they can check.
Hope this makes sense & works for you.
For this project, I am coding smart contracts for Ethereum using Solidity.
In the following code, the variable numCertificates should initially be 1. Nonetheless, newCertificateId is 0 when assigned. According to the debugger (I'm using remix.ethereum.org), for some reason, numCertificates becomes 0 as soon as the line where newCertificateId is assigned is reached.
I have played around with remix a lot, and according to it, numCertificates is 1 until exactly the aforementioned line is reached. Also, I think that if I modify numCertificates in another function, the variable stays the same as before.
My attempts at trying to figure this out lead me to believe that when I access numCertificates, I am not accessing the public state variable but something else.
Why does this code have this problem and how can it be solved?
pragma solidity ^0.4.21;
contract MyToken {
// ... lots of irrelevant stuff here
mapping (uint64 => Certificate) public certificates;
uint64 numCertificates = 1;
// ... lots of irrelevant stuff here
function MyToken() public {
// ... likely irrelevant code
}
function produceCertificate(
// ... likely irrelevant parameters
) public {
// Create the certificate in memory
numCertificates;// only for debbuging
Certificate storage newCertificate = constructCertificate(meterId, timestamp, carbonMitigationValue, owner);
uint64 newCertificateId = numCertificates;
newCertificate.certificateId = newCertificateId;
// Save the certificate
certificates[newCertificateId] = newCertificate;
numCertificates++;
}
function constructCertificate(
uint64 meterId,
uint32 timestamp,
uint48 value,
address owner
) internal returns (Certificate storage newCertificate) {
newCertificate.meterId = meterId;
newCertificate.timestamp = timestamp;
newCertificate.value = value;
newCertificate.owners.push(owner);
newCertificate.ownershipSplit[owner] = value;
newCertificate.burned = false; // by default new certificates are fresh
return newCertificate;
}
}