问题
I read some doc about storage
, memory
and view
, pure
, but I don't fully understand them. I have following code:
contract {
struct Random {
uint32 state;
uint8 i;
}
function main() pure internal {
Random rand = Random(seed, 0);
...
}
function get_rand(Random rand, uint8 n) pure internal returns (uint16) {
assert(n <= 16)
while (true) {
if (rand.i >= 8) {
rand.state = xorshift32(rand.state);
rand.i = 0;
}
uint8 r = uint8(rand.state >> (rand.i << 4)) & 0x0f;
rand.i += 1;
if (r < n) {
return r;
}
}
}
}
My questions are:
1) Should I mark storage
or memory
for the local variable in main
? And what should I mark for the argument in get_rand
?
2) Will the mutation work? Say, I read that a pure
function cannot change state variables, and memory variables are copied. Is marking both as storage
enough? Should I still declare pure
for get_rand
if it changes its argument?
Thanks
回答1:
view
and pure
are function modifiers that describe how the logic in that function will interact with the contract state. If your contract is going to read from storage, but not write to is, you would use the view
(or constant
which is exactly the same) modifier (See view functions documentation). If you're not going to read or write from contract state, and everything you do only works with memory variables, then it's a pure function.
Should I mark storage or memory for the local variable in main? And what should I mark for the argument in get_rand?
By default, structs are storage
variables and it will attempt to write your struct to state. This is where you need to be careful because you can actually overwrite your state if you use a storage
variable where you should be using memory
. Example:
contract C {
uint _var;
function f() public {
Random r;
...
}
}
In this case, r
is uninitialized storage pointer which causes the variable to point to storage slot 0. When you set some variable inside the struct (r.state = 100;
), it will write that value to slot 0 which overwrites the value at _var
.
When you want to create a new struct as a local variable, you want to use the memory
modifier and then set it to a state variable (or add it to a state mapping/array). When you want to read a struct from a mapping/array into a local variable, use storage
.
With the example you've provided, you want to set this to be a memory
variable. Read this section of the Solidity docs very carefully.
Will the mutation work? Say, I read that a pure function cannot change state variables, and memory variables are copied. Is marking both as storage enough? Should I still declare pure for get_rand if it changes its argument?
No, it will not change the state of your contract. While local struct variables are storage
by default, function arguments are always memory
by default (even structs). Modifying rand
inside get_rand
will not modify any state. If you changed the function to access state, you would get a compilation error because of the pure
modifier.
回答2:
State variables are values which are permanently stored in contract storage. They are declared inside contract scope and outside function scope. Like this:
pragma solidity ^0.4.0;
contract SimpleStorage {
uint storedData; // State variable
// ...
}
So overall hierarchy of a contract is like this:
Contract
--/ State Variables
--/ Functions
Other than that, I couldn't understand what you are asking really. Maybe you should ask clearly and in separate questions instead of asking them all in a single question vaguely.
来源:https://stackoverflow.com/questions/49613580/what-are-state-variables-in-solidity