Looking through an OpenZeppelin tutorial, I came across this code snippet:
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
contract GameItem {
constructor() ERC721("GameItem", "ITM") {}
What is the syntax in the constructor that allows a class instance to be passed in after constructor()? I can’t seem to find any reference to this in the Solidity docs
It's invoking a parent constructor, in this case the parent class is named ERC721. It's the same as calling super.constructor() or parent.constructor() in some other languages.
In order to call the parent constructor, your contract needs to actually inherit from it:
contract GameItem is ERC721 {
Solidity supports inheritance from multiple parents. That's why you cannot just use an ambiguous keyword such as parent. By explicitly stating the parent class name, you can specify which values you want to pass to which parent:
pragma solidity ^0.8;
contract Parent1 {
constructor(string memory message1) {}
}
contract Parent2 {
constructor(string memory message2) {}
}
contract Child is Parent1, Parent2 {
constructor() Parent1("hello") Parent2("world") {}
}
Docs: https://docs.soliditylang.org/en/v0.8.13/contracts.html#arguments-for-base-constructors
Related
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.
I'm trying to fund a smart contract with LINK tokens. I get an error "VM error: revert. revert 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." My code is simple:
// SPDX-License-Identifier: MIT
pragma solidity >=0.5 <0.9.0;
//Remix Imports
import "https://github.com/smartcontractkit/chainlink/blob/develop/evm-contracts/src/v0.6/ChainlinkClient.sol";
import "https://github.com/smartcontractkit/chainlink/blob/develop/evm-contracts/src/v0.6/vendor/Ownable.sol";
import "https://github.com/smartcontractkit/chainlink/blob/develop/evm-contracts/src/v0.6/vendor/SafeMathChainlink.sol";
import "https://github.com/smartcontractkit/chainlink/blob/develop/evm-contracts/src/v0.6/interfaces/LinkTokenInterface.sol";
import "https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
contract SimpleStorage {
SimpleStorage2[] simpleStorage2s;
function set() public payable returns(address) {
SimpleStorage2 a = new SimpleStorage2();
simpleStorage2s.push(a);
LinkTokenInterface link = LinkTokenInterface(a.getChainlinkToken());
link.transfer(address(a), 100);
return address(a);
}
}
contract SimpleStorage2 is ChainlinkClient, Ownable {
function getChainlinkToken() public view returns (address) {
return chainlinkTokenAddress();
}
}
Solidity compiler 0.6.12. What am I doing wrong? How do I get this to work?
Get the address of the contract that you've deployed, and send it LINK.
You can read the Chainlink documentation for more information.
It looks like you're using remix.
Get the address of your contract.
Paste it into your Metamask
3. Send your contract LINK
You'll get a few notifications to confirm.
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.
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.
What happens ?
msg.sender.transfer(msg.value);
remix.eth is just telling me
errored: Cannot read property 'op' of undefined
Works fine for me:
pragma solidity ^0.4.0;
contract Test {
function () payable {
msg.sender.transfer(msg.value);
}
}
I get invalid opcode if I don't specify the function is payable.