You need to add the constant
keyword to the test()
function like:
pragma solidity ^0.4.0;
contract Test {
mapping (address => uint256) weismap;
function bet(uint vote) payable returns (uint256 weis) {
if (msg.value==0)
throw;
weismap[msg.sender]= msg.value;
return weismap[msg.sender];
}
function test() constant returns (uint myVote) {
return 1;
}
}
Calling bet(...)
with the value 2. Note that I'm sending 2 ethers as well with the transaction:
Now I call test()
AND I've left the value 2. This call to test()
fails as the constant function is being called as a transaction, not a read of the values off the blockchain:
If I call test()
AND I've set value to blank, this call to test()
succeeds as the constant function is being called as a read of the values off the blockchain:
The main issue with your code is that you are trying to return a uint[]
which is an array
, however you defined your variable as a mapping of mappings, and mapping
and array
are different types.
You could get your code to compile like this:
pragma solidity ^0.4.24;
contract test {
mapping (address => uint[]) public transactions;
constructor() public {
transactions[msg.sender].push(123456);
transactions[msg.sender].push(789101);
transactions[msg.sender].push(865436);
}
function getTransactions() public view returns (uint[]) {
return transactions[msg.sender];
}
}
However in general, I would not recommend a single function which returns all the values. While this may be useable in a web front-end, it will not scale as a normal contract function, since eventually you will reach a number of objects in the array where the gas cost to return them all will be too large for the evm.
Instead, I suggest you break it into two functions:
pragma solidity ^0.4.24;
contract test {
mapping (address => uint[]) public transactions;
constructor() public {
transactions[msg.sender].push(123456);
transactions[msg.sender].push(789101);
transactions[msg.sender].push(865436);
}
function getTransactionsLength() public view returns (uint) {
return transactions[msg.sender].length;
}
function getTransactionsValue(uint index) public view returns (uint) {
return transactions[msg.sender][index];
}
}
One is getTransactionsLength()
, and the other is getTransactionsValue()
. Both of these functions return just a single uint, which means you will have predictable output size and gas costs, which means it can be used in other parts of your contract.
Furthermore, you will also create better user experiences by controlling the number of values you are showing. If you need to show all the values, you could first get the length
, and then loop the value call from 0 to length-1
.
But even better, you may only want to show the last 10 transactions in the UI, where then you can loop from length-1 to length-11
. These may seem like complexities at first, but in reality will be simplifications to your dApp is it grows; things you will really come to appreciate from immutable programs :)
Best Answer
That's a very good question. It touches upon a detail that is probably not very well known, even though it's documented (Rational and Integer Literals):
In other words, literal numbers like
100
and3
are notuint
s or any other integer type. Instead Solidity has a special internal type for them and expressions using only literals are evaluated at compilation time and with arbitrary precision. Only when you assign them or use them in an expression with a non-literal they get converted to an actual integer type.Another important fact is that you can mix integer and rational literals and still retain these properties. So
100/3
is still of a literal type whileuint(100)/3
,100/uint(3)
oruint(100)/uint(3)
all force a conversion touint
. Foruint
, operator/
is the integer division that silently discards the fractional part.So the result of
uint(100)/uint(3)
is alreadyuint
and you can return it without extra conversion.100/3
is of the literal type and the compiler does not silently truncate literals. It instead requires you to do an explicit conversion touint
(i.e.uint(100/3)
) to signal that it's really what you want to happen. It's not needed with100/2
because the result is an integer literal that does not require truncation and the compiler can implicitly convert it touint
.