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.
Related
I am following a tutorial.
In that i imported one contract to another contract.
Then i used the name of imported contract as the datatype name to initialise an array.
How is it possible to use a contract name as datatype ?.
import "./SimpleStorage.sol"; //importing another contract
contract StorageFactory {
SimpleStorage[] public simpleStorageArray ; //global variable
function createSimpleStorageContract() public {
SimpleStorage simpleStorage = new SimpleStorage();
simpleStorageArray.push(simpleStorage);
}
function sfStore(uint256 _simpleStorageIndex, uint256 _simpleStorageNumber) public {
SimpleStorage simpleStorage = simpleStorageArray[_simpleStorageIndex];
simpleStorage.store(_simpleStorageNumber);
}
function sfGet(uint256 _simpleStorageIndex) public view returns(uint256){
SimpleStorage simpleStorage = simpleStorageArray[_simpleStorageIndex];
return simpleStorage.retrieve();
}
}
Contract and interface type acts as a pointer to the target contract. The code assumes that the target contract implements all external and public functions of this type.
In your case, StorageFactory assumes that all addresses stored in the simpleStorageArray array implement the interface of SimpleStorage.
So if SimpleStorage implement this function: get() external returns (uint256), StorageFactory is going to expect this function to return a binary response with the length of 256 bits, and then cast it to unsigned integer.
Docs: https://docs.soliditylang.org/en/v0.8.17/types.html#contract-types
// contracts/transferownership.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract transferownership is ERC20, Ownable {
uint256 lastpresence;
uint256 amount = balanceOf(msg.sender);
constructor(uint256 initialSupply) ERC20("interorm", "intr") {
_mint(msg.sender, initialSupply);
}
function presence() public onlyOwner {
lastpresence = block.timestamp;
}
function changeOwnership(address newowner) public {
require(lastpresence < block.timestamp - 356 days);
transfer(newowner, amount);
_transferOwnership(newowner);
lastpresence = block.timestamp;
}
}
//The transaction has been reverted to the initial state.
Reason provided by the contract: "ERC20: transfer amount exceeds balance".
Debug the transaction to get more information.
//basically the program should transfer the whole amount of money
and then change ownership but im getting this error
everytime i call the changeownership function
To fix it, simply declare the amount variable in the changeOwnership function. That is before you call the transfer method.
uint256 amount = balanceOf(msg.sender);
transfer(newowner, amount);
Ensure that you set the changeOwnership function as payable.
function changeOwnership(address newowner) payable public {
Explanation: When you debug the function, the way you have it originally, you will find that the value=0, this is because the amount declaration in the global variable is not called in the stack when the transfer method is called.
To make the amount available in the call stack, you will have to parse it in the function.
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.
When releasing the ERC-20 token,
OZ(OpenZeppelin)'s util Context.sol is inherited.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/*
* #dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
I read that when using a meta-transaction solution such as EIP-2771, Context.sol is useful.
https://forum.openzeppelin.com/t/help-understanding-contract-context/10579
function _msgSender() internal view virtual override returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
// The assembly code is more direct than the Solidity version using `abi.decode`.
assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) }
} else {
return super._msgSender();
}
}
But in the case of ERC-20, why shoud I use Context.sol's _msgSender()?
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
Doesn't make it more secure?
What is the usage of Context.sol within ERC-20?
Thank you in advance.
Context is needed to implement metatransactions, or gas free transactions for token transfers.
More about Context in Gas Station Network documentation.
If you do not plan to support this feature (hint: no one does today) you do not need to Context.
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.