I write a simple contract to test the event like the following code:
pragma solidity ^0.6.12;
contract EventTest {
address public router;
event RouterUpdated(address indexed newAddress);
function setRouter(address newAddress) public {
router = newAddress;
emit RouterUpdated(newAddress);
}
}
Why the transaction event function name does not appear?
Check result
It's stored on the blockchain in the form of keccak256 hash of the event signature.
keccak256("RouterUpdated(address)") == 0x7aed1d3e8155a07ccf395e44ea3109a0e2d6c9b29bbbe9f142d9790596f4dc80
It's not translated to the original RouterUpdated simply because Etherscan doesn't translate it to the human-readable form.
Since hash is a one-way function, this translation is usually done using a dictionary, where the key is the hash and the value is the input.
They translate function signatures to function names in some parts of their UI, but for some reason they chose not to translate the event signatures to event names.
Related
My doubt is from the below code:
contract RandomNumber{
uint number;
function get_random() public{
bytes32 ramdonNumber = keccak256(abi.encodePacked(block.timestamp,blockhash(block.number-1)));
number = uint(ramdonNumber);
}
}
We assign a random number to the variable number but if I don't set number public or create another public function to retrieve the value then nobody would know the exactly value through Etherscan. But what about the miners? Can they retrieve these unrevealed data in some ways?
I have tried:
Google, Ethereum whitepaper, Solidity documentation
Assuming that the contract is deployed on a public network (e.g. Ethereum), then the value is always readable.
Not directly through the autogenerated getter function (that's available only for public properties), which means it's not available onchain.
But anyone (including miners) can create an offchain app (for example in JavaScript) that queries the specific storage slot where the value is stored - in this case it's in slot number 0. And it returns the "secret" value.
JS code using ethers library, a wrapper to RPC API of Ethereum nodes:
const number = await provider.getStorageAt(CONTRACT_ADDRESS, SLOT_NUMBER);
Docs: https://docs.ethers.org/v5/api/providers/provider/#Provider-getStorageAt
And the actual RPC API method: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat
I have a problem about handle function value.
likes the title ..
I already know contract's function call other contract's function depend on:
addr.call(abi.encodeWithSignature("function(parameter_type)", parameter ));
but what if I want to handle the function's value(ex:bool) temporarily (memory) for condition .
I had seen abi.encodePacked() , but I don't even know what parameter feedback to me (compile error , different parameter type), that I can't even storage it .
Some articles write it only for bytes, uint , but I only want to do condition(bool).
You don't need to do that .call unless you want to preserve the msg.sender.
If the msg.sender does not matter for you, I recommend you to look at interfaces. Now, what you have to do, is to create an interface with the functionB definition of that you want to call, and then call it.
Example:
(some deployed contract)
contract MySecondContract {
function functionB() public returns(bool) {
return true;
}
}
(get the deployed contract address and use it in your code like)
interface IMySecondContract {
function functionB() external returns(bool);
}
contract MyFirstContract {
function functionA() public returns(bool) {
bool result = IMySecondContract(MySecondContract-address-here).functionB();
return result;
}
}
If you do want to keep using .call, here you can see that the .call method returns two values.
Something like
(bool success, bytes myReturn) = addr.call(...);
and then this, might work.
Something else that might help is this new way of debugging.
I am trying to learn solidity through coding the smart contract below (see snippet below) .
I have been able to successfully compile (i.e. without bugs) the smart contract, the object of which is to payout an inheritance from one ethereum wallet address to another (e.g. a family member).
I have also been able to deploy it but I get the following error message (also see attached pic) when i try to transfer an inheritance to a payee.
Any help is greatly appreciated !
error message:
"transact to Will.setInheritance errored: VM error: revert.
revert The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value. Debug the transaction to get more information"
pragma solidity ^0.5.1;
//Use a double forward slash to write a like this one
// Line1 : First we nominate which version of the SOLIDITY code we are using.
//This is always the first step in our code.
// Here we tell REMIX that the the source code we are using is version 0.5.1 or above (by using the ^ - carrot symbol)
// We will start building our SC which will eventually split the inheritance of a persons will (e.g. Grandfather) amongst the Family members
contract Will {
//Line 9 : Each new contract must be named as “contract”, then the name with the first letter always CAPITALIZED, followed by open/close curly brackets to contain the logic.
address owner;
uint fortune;
bool isDeceased;
// Line 13: here we declare the variables of the smart contract - each variable must be listed along with its variable type in SOLIDITY
// Line 13: owner is of the address type of variable in SOLIDITY (unique variable in SOLIDITY - refers to an ethereum network address)
// Line 14: fortune is of the type uint (unsigned integer = a positive only integer)
// Line 15: isDeceased is a boolean variable (i.e. TRUE or FALSE type)
constructor() public payable {
owner = msg.sender;
fortune = msg.value;
isDeceased = false;
}
// Line 22: here we use a constructor function to set these values in he contract
// The “public” keyword is what’s known as a “visibility modifier” which tells the contract who is allowed to call the function.
// Public means that the function can be called within the contract and outside of it by someone else or another contract.
// The “payable” keyword allows the function to send and receive ether.
// When we deploy the contract we can initialize it with an ether balance.
// When the contract receives ether, it will store it in its own address.
// Then we will use the SC to transfer the ether to another adress (or inheritor)
// Line 23: we set the owner to “msg.sender”, which is a built-in global variable representative of the address that is calling the function.
//In this case, it will be the owner of the funds.
// Line 24: The fortune is set to “msg.value”, which is another built-in variable that tells us how much ether has been sent.
// Line 25: We set the isDeceased to false
modifier onlyOwner {
require (msg.sender ==owner);
_;
}
modifier mustBeDeceased {
require (isDeceased == true);
_;
}
// Modifiers are add-ons to functions that contain conditional logic.
// Line 41 declares “onlyOwner” modifier.
// If added to a function, it can only be called if the caller (msg.sender) is equivalent to the owner variable as stated above (remember how we set the owner in the constructor). We will need this to allow the distribution of funds, which will be implemented later.
// The “require” keyword states that we want isDeceased to be true otherwise solidity will throw an error and the execution will stop.
// The “_;” at the end tells the execution to shift to the actual function after it’s done reading the modifier.
// Now we must declare how the inheritance is divided amongst the family members.
// We will need their public wallet keys (addresses) and their desired allotments.
// First we create a list to store the wallet addresses (of the family members)
// And we create a and a function that sets the inheritance for each address.
address payable[] wallets;
//ABOVE WE HAVE TO ENTER payable to tell SOLIDITY that the address for the payout of the money is the wallet address
// function will not work without adding "address" here
mapping (address => uint) inheritance;
function setInheritance(address payable _wallet, uint _inheritance) public onlyOwner {
wallets.push(_wallet);
inheritance [_wallet] = _inheritance;
}
// Line 67: declares an empty array called “wallets” for storing the family members’ wallet addresses.
// This is a list-like data structure . The square brackets after “address” indicate it’s an array of items rather than a single variable.
// Line 69: Creates a mapping from an address type to a uint type named “inheritance”
// We will use this for distributing the inheritance to a family members wallet (It’s the equivalent of a “dictionary” in other languages such as Python and Javascript, Key/Value Pair).
// Line 71 declares the function that adds an address to the (empty) inheritance array we just created and then sets the inheritance to be provided to this address.
// We added the the “onlyOwner” modifier we added to this function, which means that only the owner of the money can distribute the funds
// Finally we create the payout function, i.e. the actual transfer of the funds
function payout() private mustBeDeceased {
for (uint i=0; i<wallets.length; i++) {
wallets[i].transfer(inheritance[wallets[i]]);
}
}
function deceased() public payable onlyOwner {
isDeceased = true;
payout();
}
}
Solidity error message i receive when i try to transfer the payment to the payee
I executed your code and examine in depth. Note that currently remix and solidity does not show good and meaningful error messages.
The problem here is your constructor function is payable:
constructor() public payable {
owner = msg.sender;
fortune = msg.value;
isDeceased = false;
}
And if you execute constructor without any value it will execute also the setInheritance will execute without error and when you try to run the deceased function which is another payable function, then the things will blast. The remix will say the constructor is payable but did not sent any value.
Please try to send some value if you want to run any payable function. Here you can write value for payable functions.
Hope it helps.
I want to declare a simple array (dynamic list), one set function to push a string in and one get function which returns all the strings saved in the dynamic array.
I search a lot but not able to find this simple stuff.
Here is my solution, you need experimental ABIEncoderV2 to return array of strings.
pragma solidity ^0.5.2;
pragma experimental ABIEncoderV2;
contract Test {
string[] array;
function push(string calldata _text) external {
array.push(_text);
}
function get() external view returns(string[] memory) {
return array;
}
}
If, finally, you want to interact with your smart contract with tools like web3j (for java) or web3js (javascript) in an application, working with dynamic arrays is not going to work because of some bugs in those libraries.
In this case you should serialize your output array. Same applies if you have an input array.
In order to change the state of the smart contract from front end inputs, wanted to submit string array to a smart contract , key value pair or objects.
Is it possible to use string array as parameter?
No solidity doesn't support arrays of strings as parameter. You would have to serialize and deserialize it in a string yourself to have the desired result but that would be expensive to do in solidity. You can test that on remix if you want. However, on remix the error message says that this function is supported in the experimental ABI encoder but I have never tested that, or how well it works with other libraries, and it is experimental after all.
As seen in below example from solidity document we can send bytes array to constructor
constructor(bytes32[] memory proposalNames) public {
chairperson = msg.sender;
voters[chairperson].weight = 1;
// For each of the provided proposal names,
// create a new proposal object and add it
// to the end of the array.
for (uint i = 0; i < proposalNames.length; i++) {
// `Proposal({...})` creates a temporary
// Proposal object and `proposals.push(...)`
// appends it to the end of `proposals`.
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
If you are trying to send string/Objects data specifically then it's better to separate out the methods and call each methods separately or within each other as currently solidity does not support that (using ABIencodere v2 is exceptional as it is only recommended for development purpose- as per on the date of this answer written)
struct A{
uint date,
B[] b
}
You can separate this out to
struct A{
uint date
}
struct B{
string goods,
uint quantity
}
so now for 1 A you can call N B from your service. Use mapping for binding both(if dependent).
In current situation it's better to design a contract which does not take bulk inputs or give out bulk outputs. However contracts are not for storage of huge data it's for storage of related data which fulfills agreement between parties