i'm trying to use a contract instance as a variable of another contract, such as the example below.
pragma solidity ^0.4.23;
contract basic {
uint num1 = 10;
function getNum1() public view returns(uint) {
return num1;
}
function setNum1(uint _num) public returns(uint) {
num1 = _num;
}
}
contract parent {
uint public num2;
basic public b;
constructor() public {
b = new basic();
num2 = 20;
}
function getNum1() public constant returns(uint) {
return b.getNum1();
}
}
while when i test the contract in remix and truffle , it worked well.
enter image description here
but util i deployed the contract "parent" on my private network, parent.getNum1() returned '0' instead of '10' as supposed.
further more, i tried other type of constructors such as take an address of 'basic' as a parameter, it didn't work as well.
i also tried some contracts thats takes another contract instance as a variable, they all didn't work well on private network.
does anybody ever meet this problem? help!!!
coming to close the question now !
i deployed my contract on ropsten test network, and the contract worked well.
it seems that my private network didn't support the usage of calling from another contract. anybody interested can have a try to see.
Related
This might be a beginner question, but the thing is confusing
I can see from samples like bellow
https://github.com/acloudfan/Blockchain-Course-Basic-Solidity/blob/93ca256bcf8c436c144425291257dcff5c3b269f/test/TestMetacoin.sol#L18
MetaCoin meta = new MetaCoin();
That a contract can be created/instantiated inside another contract, I want to understand what is happening here? does this create a new contract and deploy, therefore having a new address? or does it works or behaves like an ordinary class like in C++ or java, etc?
I dont know what is the context of the meta instance at this point.
Can someone help explain?
Secondly, this might be related,
What does it mean when two contracts are defined in a single Sol file and the second contract instantiated the first one like below?
pragma solidity 0.4.21;
contract Base {
uint public dataA;
bytes32 public dataB;
function setAB(uint a, bytes32 b) public {
dataA = a;
dataB = b;
}
function getA() public view returns(uint) {
return dataA ;
}
function getB() public view returns(bytes32) {
return dataB ;
}
}
contract Extra {
Base base;
function Extra() public {
base = new Base();
}
...
}
Does the contract base deployed and will have its own address?
I'm trying to write a TicTacToe game on remix.ethereum.org but all of a sudden all my test accounts show 0 ETH balance, so I can't use them to deploy my contracts anymore.
Here is the solidity code that I was deploying when it happened:
pragma solidity ^0.4.19;
contract TicTacToe {
uint8 public boardSize = 3;
address[3][3] board;
address public player1;
address public player2;
constructor() public {
player1 = msg.sender;
}
function joinGame() public {
assert(player2 == address(0));
player2 = msg.sender;
}
function setStone(uint8 x, uint8 y) public {
board[x][y] = msg.sender;
}
}
New test accounts still show 100 ETH upon creation.
I don't think this is anything to do with deploying your Solidity code.
What blockchain environment are you using? It is most likely a problem there.
Remix environment menu
I have deployed a very basic solidity contract (pragma solidity^0.4.0) to Rinkeby. When I call the getters on my state variables, nothing is returned and I do not understand why. To compile the contract I'm using "solc": "^0.4.25"
Using Remix to test, the call to the getter works locally without issue. However, the call doesn't work on my contract on Rinkeby.
Here is my solidity code...
pragma solidity^0.4.0;
contract Contest {
address public manager;
uint public submissionCost;
uint8 public votesPerSubmission;
constructor (uint _submissionCost, uint8 _votesPerSubmission) public {
manager = msg.sender;
submissionCost = _submissionCost;
votesPerSubmission = _votesPerSubmission;
}
modifier restricted() {
require(msg.sender == manager, "Not authorized.");
_;
}
function adjustSubmissionCost(uint32 newCost) public restricted {
submissionCost = newCost;
}
function adjustVotesPerSubmission(uint8 newVotes) public restricted {
votesPerSubmission = newVotes;
}
}
The address of the deployed contract on Rinkeby is
0xacBd19113e0D8122E18DF48A320b635fB5D7Cdd0
https://rinkeby.etherscan.io/address/0xacbd19113e0d8122e18df48a320b635fb5d7cdd0
When calling any of the public variables from Remix, I expect a return value, however I only receive the message call to Contest.manager in the Remix console and nothing more.
I get the same behavior in my web3 dapp, with zero return when I try...
await Contest.methods.manager().call()
So, from what I understand, it's a good idea to use temporary contracts and redeploy when a change is necessary. Let's assume that I controlled a smart lightbulb with the following code.
pragma solidity 0.4.24;
contract Lightbulb {
enum LightState { off, on }
address public owner;
LightState light;
LightState constant defaultChoice = LightState.off;
uint public cost = 1 ether;
constructor () public {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function turnOn() public payable {
require(msg.value == cost);
light = LightState.on;
}
function turnOff() public {
light = LightState.off;
}
function getState() public view returns (LightState) {
return light;
}
}
Should I just redeploy the contract if I wanted to change the cost? Also, I could put the cost in a constructor, but if I wanted to change the cost I would still have to redeploy so does that really matter?
Contract deployment is very costly and you typically want to avoid it whenever possible. You would deploy a new contract when business rules change. For a simple state change operation like the one you described, you would want to provider a setter for the cost that uses the onlyOwner modifier to restrict access.
I have the following solidity code.
pragma solidity ^0.4.21;
contract Parent {
uint public childCount;
Child[] public children;
function makeChild(string name) external {
children.push(new Child(address(this), childCount, name));
childCount++;
}
function renameChild(uint index, string newName) external {
require(address(children[index]) != 0);
Child thisChild = Child(address(children[index]));
if (thisChild.isUpdated()) {
thisChild.rename(newName);
}
}
}
contract Child {
address parentAddress;
uint index;
string public name;
bool public isUpdated;
constructor(address parent, uint _index, string _name) public {
parentAddress = parent;
index = _index;
name = _name;
isUpdated = false;
}
function rename(string newName) external {
name = newName;
}
function renameViaParent(string updateName) external {
isUpdated = true;
Parent(parentAddress).renameChild(index, updateName);
}
}
I have been testing this code via Remix Solidity IDE. When I run in Javascript VM, I can create a child from parentInstance.makeChild("childName") and rename it using childInstance.renameViaParent("newName").
However when I switch to an Ethereum private chain, i.e. Injected Web3, I can still create the child, but fail in renaming using childInstance.renameViaParent("newName"). It gives the message:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
Invalid JSON RPC response: {"id":1830,"jsonrpc":"2.0","error":{"code":-32603}}
I tried to remove thisChild.isUpdated() condition check in renameChild(index, newName) and the code ran fine in both JS VM and private Web3. This is why I believe accessing the member variable isUpdated of Child from Parent is causing the problem.
What is wrong here? Probably with my private chain set up? How is it different from the Javascript VM Remix is using?
I am using geth-linux-amd64-1.8.6-12683 to run my private chain.