Why do I need parenthesis to access a Solidity contract variable in python? - ethereum

inside a Solidity contract there is a declaration as follows:
contract Lottery is VRFConsumerBase, Ownable {
address payable[] public players;
...
...
elsewhere in the same contract,there is a an assignment as follows:
....
....
recentWinner = players[someIndex];
....
....
}
the deploy.py Python script is used to deploy the contract. the function deploying the contract is:
def deploy_lottery():
Lottery.deploy(....)
....
....
After deployment and doing other stuff... the contract's recentWinner variable is accessed from python script using parenthesis as follows:
def end_lottery():
print(f"{lottery.recentWinner()} is the winner!")
My rather basic question is, why are parenthesis used? recentWinner is not a function that was defined in the Lottery contract. If I ran the script without the paranthesis, I get the following output.
<ContractCall 'recentWinner()'> is the winner!
Terminating local RPC client...
so it seems like the paranthesis is necessary. can somebody explain what is going on please? why should I treat this variable like a function in order to retrieve its value? if you can also point me to some related posts/reading material that would be much appreciated. thank you!

EVM does not have public variables, only public accessor functions.
Behind the scenes, the Solidity compiler generates a function called recentWinner() for you. This is called accessor or getter function. Unlike in Java etc. languages there is no get prefix for the function.

Related

solidity - Smart contract - function pass parameter

I'm having problems setting a value in a deployed BSC smart contract, below is the problematic solidity function, is the fact '_value' has been used not 'value' as the pass parameter ?
function setSwapTokensAtAmount(uint256 _value) external onlyOwner
{
swapTokensAtAmount = _value;
}
I have looked at other contracts and can't see any that use the '_' when labelling a pass parameter value, which can be used (from my understanding) denote a public or private variable.
It's a common practice to name function-scoped variables starting with underscore. But naming the variable with or without underscore doesn't have any effect on the resulting functionality.
I see that your function uses the onlyOwner modifier. While your code doesn't show the modifier implementation, we can assume that it controls that only authorized sender can execute the function.
So a very likely reason why you cannot update the variable is that you're trying to execute the function from a different address than the authorized owner.

How do you define operator when creating new ERC-777?

My understanding is that you can define an operator when instantiating a custom ERC-777, that can make transfers without needing to be approved by the senders using the operatorSend function. However, can't seem to get the address of the contract that deploys the token into the inherited constructor. I tried pushing the address into the array in the body of the constructor, but that doesn't seem to take.
contract MainToken is ERC777 {
address[] ops=;
constructor () ERC777("MYTOKEN", "MTK",ops) {
ops.push(msg.sender);
}
...
}
If I try putting it directly into the constructor like so ERC777("MYTOKEN", "MTK",[msg.sender]), I get
Invalid type for argument in modifier invocation. Invalid implicit
conversion from address[1] memory to address[] memory requested.
Solidity currently doesn't allow defining a dynamic-size array in one expression. Note: [msg.sender] from your example is a fixed-size array definition.
Also, your approach with defining the ops property doesn't work, because of the order how EVM processes the constructor.
Storing child (MainToken) constructor arguments to memory (in your case no arguments)
Executing parent constructor.
In your case the execution of ERC777("MYTOKEN", "MTK", ops) fails, because the storage variable ops is not available yet.
Executing child constructor (in your case ops.push(msg.sender);)
So the easiest Solution I could come up with, is passing the address from the MyToken argument. This is useful if you have control over the deployment process and can manually pass the value of msg.sender when you're deploying the contract.
pragma solidity 0.8.4;
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC777/ERC777.sol';
contract MyToken is ERC777 {
constructor(address[] memory defaultOperators)
ERC777('MYTOKEN', 'MTK', defaultOperators) {
}
}
If you're not going to have control over the deployment and need to assign msg.sender in constructor, I suggest copying the ERC777 contract locally and modifying its constructor, so that it only adds the msg.sender.

Solidity tx.destination.call.value(tx.value)(tx.data)

I came across this Solidity code:
tx.destination.call.value(tx.value)(tx.data)
but don't understand how it works... especially the tx.data at the end.
This statement is calling a function represented by tx.data on the address at tx.destination passing in wei (tx.value).
To break it down further:
tx.destination is an address. An address has built in members and functions, including call which allows you to execute functions on a contract without the ABI (see Address type definition). For example, you can call a method foobar on a contract without a defined interface like this:
contractAddress.call(bytes4(keccak256("foobar(uint256,uint256)")), val1, val2); // where val1 and val2 are the uint256 parameters to pass in
Using call alone will use some default values when calling the other contract's method. For example, all of the remaining gas will be forwarded. If you want to change those values, you can adjust it by supplying your own gas and/or wei values, which looks like a function call itself:
contractAddress.call.value(9999999)();
This will send 9999999 wei to contractAddress. You can override both the gas and ether sent by chaining multiple function calls:
contractAddress.call.value(99999999).gas(77777)();
The last set of parens in both examples indicate to use the fallback function when sending the wei. You can see a similar example in the Solidity docs FAQ.
If you wanted to call something other than the fallback function, you would combine the 2 examples above, which is what the code you posted is doing. The fact that they are using tx is a bit confusing since that is normally a built-in reference, but they are likely shadowing that and it's referencing a struct with destination, value, and data members.

eth.estimateGas fails with contract address as second parameter

Newbie.
There is a go-ethereum method:
eth.estimateGas({from:'firstAccount', to:'secondAccount'})
that works well,
but same method with contract address like:
eth.estimateGas({from:'firstAccount', to:'contractAddr'})
fails with error
gas required exceeds allowance or always failing transaction
I have looked into go-ethereum source code and it has the line, that contains proposal to use contract address as second parameter:
https://github.com/ethereum/go-ethereum/blob/master/accounts/abi/bind/base.go#L221
The question is: is there any possibily to use eth.estimateGas with contract address as second parameter and how to avoid above error?
Thank you.
You're not specifying what you're executing in the contract, so there's nothing to estimate. When you estimateGas for a transfer to an EOA account, there is no contract code to execute, so there is no message data to be sent as part of the transaction object. If you're estimating gas on a contract call, you need to include the data for the contract.
For example, if you want to estimate gas to setValue(2) method in this contract
pragma solidity ^0.4.19;
contract SimpleContract {
uint256 _value;
function setValue(uint256 value) public {
_value = value;
}
}
your call would be
var data = '552410770000000000000000000000000000000000000000000000000000000000000002';
eth.estimateGas({from: fromAccount, to: contractAddress, data});
The value for data comes from encoding the function signature and the parameter value(s). You can use a simple tool (like https://abi.hashex.org) to generate this. You just enter the function name along with the parameter argument types and their values, and it will generate the message data for you. You can also do this using web3js.
EDIT - I neglected to consider contracts with fallback functions. Executing estimateGas on a contract without passing in message data provide the estimate for contracts that have a fallback function. If the contract does not have a fallback function, the call will fail.

How are multiple arguments stored in a message in Switchyard

How are multiple arguments passed to a service in Switchyard stored in the message? For example, if I define a service contract as
public void service(String param1)
I know that param1 becomes the body of the message. What if the contract is defined as
public void service(String param1, String param2)
How are both arguments stored in the message, and how would I access each of them in a Camel route?
Switchyard project doesn't accept multi-arguments.
Thus one would need to create a separate class and pass the attributes inside the object.
Keep a watch on this forum too - https://developer.jboss.org/message/909685
Thanks!