In Solidity, can the constructor function have the same name as the contract? - function

According to this article, the constructor - or initialization - function has the same name as the contract. However, the remix compiler returns an error when I have a function with the same name, saying "defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead."
So, my question is, is using the same name in this situation something that should simply be avoided? (Perhaps it is an out of date practice?)

Since Solidity v0.4.23, constructors are now specified using the constructor keyword:
constructor () {}
Just to compare with the old ways, say we have a Smart Contract called Employee, in the past, you'd specify the contract with its constructor like this:
contract Employee {
// constructor
function Employee() public {
// ...
}
}
But the acceptable way to specify the Employee Smart Contract now is:
contract Employee {
// constructor
constructor() public {
// ...
}
}
Using the name of a contract as its constructor is now deprecated.

Related

Is it possible to call methods of contract's initializer during its initialization?

I tried to deploy following smart contracts
pragma solidity 0.8.17;
contract Contract1 {
constructor() {
new Contract2(address(this));
}
function foo() public pure returns (string memory) {
return "bar";
}
}
contract Contract2 {
Contract1 contract1;
constructor(address _contract1) {
contract1 = Contract1(_contract1);
contract1.foo();
}
}
but it fails with following message:
The transaction has been reverted to the initial state. Note: The
called function should be payable if you send value and the value you
send should be less than your current balance. Debug the transaction
to get more information.
Seems like it's impossible to call methods of contract's initializer (the contract that created an instance of current one) during its initialization.
My question is how it happens that address of the Contract1 is already exists, but it's impossible to call any of its methods from the constructor of Contract2?
The address of Contract1 is not yet available when the constructor of Contract2 is called. The address of Contract1 is only available after the constructor of Contract1 has finished executing.
This means that the constructor of Contract2 cannot call any methods of Contract1 until after the constructor of Contract1 has finished executing.
In this case you can deploy the Contract1, wait for the tx complete and after deploy the Contract2 using the address of Contract1 in constructor arguments.

Explicit type conversion not allowed from "int_const" to "contract"

I am trying to deploy a contract from another contract following the example from here
At some point the example states:
Instanciating a new Counter for someone will look like this:
function createCounter() public {
require (_counters[msg.sender] == Counter(0));
_counters[msg.sender] = new Counter(msg.sender);
}
We first check if the person already owns a counter. If he does not own a counter we instantiate a new counter by passing his address to the Counter constructor and assign the newly created instance to the mapping.
However, when I try that in my factory contract:
pragma solidity >=0.7.0 <0.9.0;
contract Factory {
mapping(address => Campaign) _campaigns;
function createCampaign(uint minContrib) public {
require(_campaigns[msg.sender] == Campaign(0));
_campaigns[msg.sender] = new Campaign(minContrib, msg.sender);
}
}
...
contract Campaign {
/* Irrelevant code skipped ... */
constructor (uint minContrib, address creator) {
manager = creator;
minContribution = minContrib;
}
compilation error pops:
from solidity:
TypeError: Explicit type conversion not allowed from "int_const 0" to "contract Campaign".
--> contracts/3_Ballot.sol:10:43:
|
10 | require(_campaigns[msg.sender] == Campaign(0));
| ^^^^^^^^^^^
What comparison is being made here exactly?
require (_counters[msg.sender] == Counter(0));
What is Counter(0)? An instance of contract (like new Counter(0)) or a type conversion of parameter 'int_const' to 'contract'?
Found this this answer which made things a bit clearer.
Apparently this is trying to compare the Contract deployed at address 0 with thatever is stored at _counters[msg.sender] (which I believe should be the address of a deployed contract).
require (_counters[msg.sender] == Counter(0));
With that in mind, I get the error is saying "we're expecting a Counter or address of contract and you give us an int".
I fixed it with Counter(address(0)).

Solidity constructor declaration and statements between function signature and visibility modifieres

I just came across this in a Solidity contract, I don't understand it. Specifically I don't understand how there can be a function call after the constructor parameters block. If it were a modifier, it would be after "public", but it is immediately after the parameters. What does MerkleTreeWithHistory(_merkleTreeHeight) mean in this context?
constructor(
IVerifier _verifier,
uint256 _denomination,
uint32 _merkleTreeHeight,
address _operator
) MerkleTreeWithHistory(_merkleTreeHeight) public {
require(_denomination > 0, "denomination should be greater than 0");
verifier = _verifier;
operator = _operator;
denomination = _denomination;
}
MerkleTreeWithHistory(_merkleTreeHeight)
Calls the parent contract constructor. It is executed before entering the sub-contract constructor.

Contract functionA call contract functionB ,and functionA can storage value

I have a problem about handle function value.
likes the title ..
I already know contract's function call other contract's function depend on:
addr.call(abi.encodeWithSignature("function(parameter_type)", parameter ));
but what if I want to handle the function's value(ex:bool) temporarily (memory) for condition .
I had seen abi.encodePacked() , but I don't even know what parameter feedback to me (compile error , different parameter type), that I can't even storage it .
Some articles write it only for bytes, uint , but I only want to do condition(bool).
You don't need to do that .call unless you want to preserve the msg.sender.
If the msg.sender does not matter for you, I recommend you to look at interfaces. Now, what you have to do, is to create an interface with the functionB definition of that you want to call, and then call it.
Example:
(some deployed contract)
contract MySecondContract {
function functionB() public returns(bool) {
return true;
}
}
(get the deployed contract address and use it in your code like)
interface IMySecondContract {
function functionB() external returns(bool);
}
contract MyFirstContract {
function functionA() public returns(bool) {
bool result = IMySecondContract(MySecondContract-address-here).functionB();
return result;
}
}
If you do want to keep using .call, here you can see that the .call method returns two values.
Something like
(bool success, bytes myReturn) = addr.call(...);
and then this, might work.
Something else that might help is this new way of debugging.

Linking together smart contracts at deployment

I'm building an application that is comprised of 3 smart contracts. The aim is to have the controller control the other two (contract A and B in the image). Previously, if I wanted to restrict the access to a smart contact, I would do it through a modifier
Example:
modifier onlyController {
require(msg.sender == controller);
_;
}
At contact creation, the smart contract would set controller to be equal to whatever ethereum address I want to make these calls ( for example the address that deployed the smart contract). The issue is that now I want the address of the controller smart contract to be the controller (in the modifier). How would it be best to do this considering I want to deploy these set of smart contacts at the same time using truffle. What would be the best way to link these, so that the controller smart contract is only able to make calls to A and B. Moreover, how does the controller have to be implemented so that the user can call function in A and B going through the controller ( so the user calls a function in the controller, then the controller calls the corresponding function in A or B)?
I am no expert in Solidity. But trying to answer as I find it little bit interesting.
You seem to be trying to implement a proxy pattern which is very common in other programming languages like java in such a way that you are providing very restricted access to certain classes in this case contracts.
In Proxy design pattern both the proxy and the class to be restricted would be implementing the same interface! I do not know much about your smart contract details.
Assuming Contract A and B implementing the same interface:
Lets assume the interface is Base.
interface Base{
function getValue() external view returns (string);
}
I need to provide controlled access to the ContractA and ContractB so only the controller could call. So lets create a modifier.
contract ControlledAccess{
address controller;
constructor() public {
controller = msg.sender;
}
modifier onlyController() {
require(msg.sender == controller);
_;
}
}
Now ContractA and ContractB should implement interface Base and inherit ControlledAccess contract.
contract ContractA is Base, ControlledAccess{
function getValue() public view onlyController returns (string){
return "Hi";
}
}
contract ContractB is Base, ControlledAccess{
function getValue() public view onlyController returns (string){
return "Hello";
}
}
In order to set the controller address to be the ProxyController address, ProxyController itself should create these contracts in its constructor. As our ProxyController contract should be able to control more than 1 contract, I think mapping might be a good choice.
contract ProxyController is Base{
string public contractKey = "a";
mapping(string => Base) base;
constructor() public {
base["a"]=new ContractA();
base["b"]=new ContractB();
}
function setContractKey(string _contractKey) public{
contractKey = _contractKey;
}
function getValue() public view returns (string){
return base[contractKey].getValue();
}
}
so you can switch to A & B via setContractKey.
Assuming there is no common functionalities between A and B :
Remove the interface in the above example.Then implement something like this.
contract ProxyController{
ContractA a;
ContractB b;
constructor() public {
a=new ContractA();
b=new ContractB();
}
function AgetValue() public view returns (string){
return a.getValue();
}
function BgetValue() public view returns (string){
return b.getValue();
}
}
I tested this and it seems to be working fine. However I am not sure of other issues like performance etc.
Can't you easily set up the controller contract as
contract ControllerContract is ContractA, ContractB {
...
}
Thus giving it access to the functions in both contract A and contract B?
I'm not sure why this way would be worse than how you are describing.
You can find some solutions at the following links:
1.) https://ethereum.stackexchange.com/questions/36524/multiple-smart-contracts
2.) https://ethereum.stackexchange.com/questions/37055/where-how-to-host-several-connected-smart-contracts
A complete article on Interactions between Smart Contracts with Solidity:
https://zupzup.org/smart-contract-interaction/
A link to another article and a sample project: https://hackernoon.com/ethereum-smart-contracts-lifecycle-multiple-contracts-message-sender-e9195ceff3ec
Hope it solves your problem. Also, you can join this community for exclusivity: https://ethereum.stackexchange.com/