Here's your function slightly modified by adding public
to numbers
so we can peek at the data:
contract C {
uint[] public numbers;
function initNumbers() {
numbers.push(1);
numbers.push(2);
}
function stateChanger(uint a) {
numbers.push(a);
}
}
Using the stripCrLf
script in How to load Solidity source file into geth, I've flattened the source code using the following command:
user@Kumquat:~$ echo "var cSource='`stripCrLf C.sol`'"
var cSource='contract C { uint[] public numbers; function initNumbers() { numbers.push(1); numbers.push(2); } function stateChanger(uint a) { numbers.push(a); } }'
I'm running a dev network using the following command (I have my password in passwordfile
):
user@Kumquat:~$ geth --datadir ~/devdata --dev --mine --minerthreads 1 --unlock 0 --password ~/passwordfile console
I paste the flattened code in the geth
command line:
> var cSource='contract C { uint[] public numbers; function initNumbers() { numbers.push(1); numbers.push(2); } function stateChanger(uint a) { numbers.push(a); } }'
undefined
And compile the code using the following command:
> var cCompiled = web3.eth.compile.solidity(cSource);
Version: 0.3.5-0/RelWithDebInfo-Linux/g++/Interpreter
path: /usr/bin/solc
undefined
Here is the Application Binary Interface:
> cCompiled.C.info.abiDefinition
[{
constant: false,
inputs: [],
name: "initNumbers",
outputs: [],
type: "function"
}, {
constant: false,
inputs: [{
name: "a",
type: "uint256"
}],
name: "stateChanger",
outputs: [],
type: "function"
}, {
constant: true,
inputs: [{
name: "",
type: "uint256"
}],
name: "numbers",
outputs: [{
name: "",
type: "uint256"
}],
type: "function"
}]
Deploy the contract on the blockchain:
> var cContract = web3.eth.contract(cCompiled.C.info.abiDefinition);
undefined
> var c = cContract.new({
from:web3.eth.accounts[0],
data: cCompiled.C.code, gas: 400000},
function(e, contract) {
if (!e) {
if (!contract.address) {
console.log("Contract transaction send: TransactionHash: " +
contract.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
}
}
})
Contract mined! Address: 0x672807a8c0f72a52d759942e86cfe33264e73934
Call your initNumbers()
:
> c.initNumbers({from:eth.accounts[0], gas: 400000})
"0x3f21e1cdb636a2cf291cd9296282a4e9c4f4ed57c65a13fedc937a97203c3a75"
...
> c.numbers(0)
1
> c.numbers(1)
2
> c.numbers(2)
0
Calling stateChanger(...)
- Method 1
> c.stateChanger(3, {from:eth.accounts[0], gas: 400000})
"0x3ecf3aa6464f93d5b062ad01b76b5dbc4302c190baf70d157a4d7607d4c7c749"
...
> c.numbers(2)
3
> c.numbers(3)
0
Calling stateChanger(...)
- Method 2
> c.stateChanger.sendTransaction(4, {from: eth.accounts[0], gas: 400000})
"0xe1d9c57ca55dbdf446e55602570888ff5efce97a91ddc5c9575d10c7c9a1f0c8"
...
> c.numbers(3)
4
> c.numbers(4)
0
Calling stateChanger(...)
- Method 3
And following is how to use the raw data sendTransaction(...)
format.
Find the function signature. Note that the uint
parameter is actually a uint256
(see the ABI format above):
> web3.sha3('stateChanger(uint256)').substr(0, 10)
"0x65060775"
Here is 5 encoded in hex and padded to 32 bytes:
0x0000000000000000000000000000000000000000000000000000000000000005
Join the data together, removing the 0x
from the hex(5) string:
0x650607750000000000000000000000000000000000000000000000000000000000000005
Here's how to sendTransaction(...)
. The to:
parameter is the address of the mined contract:
> var result = web3.eth.sendTransaction({
from: eth.accounts[0],
to: "0x672807a8c0f72a52d759942e86cfe33264e73934",
data: "0x650607750000000000000000000000000000000000000000000000000000000000000005",
gas: 400000}
)
undefined
> result
"0x420d4256718b4326967677da2e460a1d361a62f3ceee386e1313d25b12c0f610"
...
> c.numbers(4)
5
> c.numbers(5)
0
Bonus 1 - estimateGas(...)
Since we have worked out the data to send with sendTransaction(...)
above.
Here is the gas used by the sendTransaction(...)
call above:
> eth.getTransactionReceipt(result).gasUsed
46888
You can use the same data format to estimate the gas using the estimateGas(...)
call:
var result = web3.eth.estimateGas({
from: eth.accounts[0],
to: "0x672807a8c0f72a52d759942e86cfe33264e73934",
data: "0x650607750000000000000000000000000000000000000000000000000000000000000005",
gas: 400000}
)
undefined
> result
46888
Bonus 2 - The Transaction Data
Set debug.verbosity(7)
and watch the transaction get removed from the transaction pool after it is executed:
> debug.verbosity(7)
...
I0730 00:13:43.918828 core/tx_pool.go:547] removed tx (
TX(07c3c717c87ce1e2b31ba144b6b751d66c90a8a69375478a5ef4e60a6f42996c)
Contract: false
From: a7857047907d53a2e494d5f311b4b586dc6a96d2
To: 672807a8c0f72a52d759942e86cfe33264e73934
Nonce: 35
GasPrice: 20000000000
GasLimit 400000
Value: 0
Data: 0x650607750000000000000000000000000000000000000000000000000000000000000004
V: 0x1c
R: 0x75ff67a969670a0f35ae415f2fa541446a71fa9b7d8ad6247ad12fd7ae3986a
S: 0x7150424ed1698792cdcf1253a79f2474e4df411610db97e36240bab50af6c80c
Hex: f889238504a817c80083061a8094672807a8c0f72a52d759942e86cfe33264e7393480a46506077500000000000000000000000000000000000000000000000000000000000000041ca0075ff67a969670a0f35ae415f2fa541446a71fa9b7d8ad6247ad12fd7ae3986aa07150424ed1698792cdcf1253a79f2474e4df411610db97e36240bab50af6c80c
) from pool: low tx nonce or out of funds
The different methods of calling (c.stateChanger(3, {from:eth.accounts[0], gas: 400000})
and c.stateChanger.sendTransaction(4, {from: eth.accounts[0], gas: 400000})
) are converted to the sendTransaction(...)
format.
In general
You can let the code run, ignoring the compiler warnings, but it's always good not to do so. Most of the time, compiler warnings are warning you about something that may cause a bug in your code. Compared to compiler errors, the difference is your code is syntactically correct, hence can be compiled, but can lead to problems, especially when someone try to do something you don't expect others to do.
Compiler warnings indicate things that might cause problems or might
have unintended effects that the programmer wasn't aware of.
A good read regarding this can be found here, and you may refer to this question as well. And most importantly, read the security considerations from Solidity docs. That may save your life!
Anyhow, the compiler is not as intelligent as you and it claims what it's lacking from in statements with Note:
as follows:
Note: Modifiers are currently not considered by this static analysis.
Sometimes, these notes may tell the occasions that you can safely ignore these warnings.
Example
One error warning you have mentioned is:
browser/TestContract 8.sol:15:3 Warning: No visibility specified.
Defaulting to "public":
Let's say you have function A(uint val) {}
. You want it to be used only within the contract due to some prior validations you need to do (This is just an example ;)). And if the function is called without validation, that may cause some unwanted executions. And the only use of function A
is to use it inside some other functions within the contract.
pragma solidity ^0.4.0;
contract Example {
function A(uint val) {
//do something with val
}
function B(uint val){
//validation of val
A(val);
}
}
Now if you keep the contract like above, since function A()
is also by default set to public, anyone who use your contract can use function A
with any uint
value and that may cause trouble. But if you had the access modifier of function A
declared as private
, this trouble won't appear since function A
can't be accessed publicly. And as your requirement is also to use function A
only inside the other functions within the contract, your goal is also achieved.
As when no access modifier is declared, the compiler assumes a function to be public and it warns you that it's setting the function to be public and ask you to check whether it should really be public. In the above case, you will get warnings regarding both functions and setting function A
to be private and function B
to be public will remove the warnings because now the compiler knows you are intentionally making function B
public and function A
private.
pragma solidity ^0.4.0;
contract Example {
function A(uint val) private {
//do something with val
}
function B(uint val)public {
//validation of val
A(val);
}
}
The warning regarding function B
being set to public is a type of warning that you can safely ignore as your intention is also the same, but the warning regarding function A
is something you should really consider.
What I suggest,
not to ignore the warning, but go through them and check whether they
do really matter, with how you expect the code to behave and try to
resolve them.
try to use the latest compiler version (atm 0.4.17), as newer stable versions tend to have less bugs and more features (hence it generates new warnings).
Some insight regarding some other warnings you get
browser/TestContract 8.sol:100:3 Warning: Function state mutability
can be restricted to pure
You may refer to this answer and this question regarding the introduction of view
and pure
type functions.
Potential Violation of Checks-Effects-Interaction pattern in
TestContract.testFunction(address):
This is for not following the pattern of Checks-Effects-Interactions as described here in the docs. Refer to the function that gets this warning and follow the pattern defined in the docs to avoid the warning.
And as per the code found in the link you posted, I think the closeSale()
warning should probably be due to the compiler assuming that there can be a chance of re-entrancy, as you are calling the member event LogSaleClosed(uint256 issuedSupply, uint256 restrictedTokens)
after interactions with token contract.
What I can suggest is having that event inside the contract token
. You can see here for re-entrancy vulnerability. It's just saying if the bad code there let another contract to withdraw money several times because they change the state variable shares after sending transaction which might take some time leaving the other contract to call the same function several times because it keeps msg.sender
value non-zero until the transaction get executed. If you see the good code there, they first set shares[msg.sender]
to zero first.
Since you are the one who developed this, you know the flow of expected events and can be sure that re-entrancy won't occur, it's safe to ignore it.
Test.transferFrom(address,address,uint256): Potentially should be
constant but is not. Note: Modifiers are currently not considered by
this static analysis.
What constant means is that it would not be changing the state. That's no state variable is changed. So normally, those functions are called constant functions and are defined with the keyword of constant. You may read this.
So if your functions are not changing any state variable, you can declare them constant. Solidity is reminding you about this.
Best Answer
Yes.
The calling contract needs two things; the address of the contract to be called, and a description of the ABI. The ABI is, in summary, a description of the function names and layout of the arguments.
You often see the contracts in the same file because it gives the compiler the information it needs about the ABI. In many cases, one or more of the contracts won't be deployed manually, but rather through a process in one or more other contracts.
You might see something like this:
In the above, the idea is that Utility is deployed, and the deployer knows the address, so they pass it into the contructor when they deploy the Factory (otherwise, how will it know?). They don't need to deploy an Instance because the Factory does that. The compiler still needs to see all three source files when Factory gets compiled. Factory needs a copy of the bytecode it's supposed to deploy with
new Instance();
and it needs the interface to Utility because the other two contracts both talk to it.A little more practical example over here: Is There a Simple Contract Factory Pattern?
Hope it helps.