How to determine correct contract compilation options? - ethereum

I've successfully deployed my contract to Kaleido but I'm having trouble figuring out how to correctly verify it. Here is the source code deploys the contract and I've verified the the address printed by the last print statement appears in my Kaleido blockchain:
from web3 import Web3
from web3.providers import HTTPProvider
from solc import compile_source
# Solidity source code
contract_source_code = '''
pragma solidity ^0.4.0;
contract Greeter {
string public greeting;
function Greeter() {
greeting = 'Hello';
}
function setGreeting(string _greeting) public {
greeting = _greeting;
}
function greet() constant returns (string) {
return greeting;
}
}
'''
compiled_sol = compile_source(contract_source_code) # Compiled source code
contract_interface = compiled_sol[':Greeter']
w3 = Web3(HTTPProvider("https://XXXXX:YYYYY#ZZZZZZZ.kaleido.io"))
contract_ = w3.eth.contract(
abi=contract_interface['abi'],
bytecode=contract_interface['bin'])
# note: when interacting with kaleido, gasPrice MUST be 0 (I think because of the consensus algorithm I chose)
# and it seems it doesn't matter what account this is sent from
construct_txn = contract_.constructor().buildTransaction({
'from': w3.eth.accounts[0],
'gas': 1728712,
'gasPrice': 0})
txn = w3.eth.sendTransaction(construct_txn)
tx_receipt = w3.eth.getTransactionReceipt(txn)
contract_address = tx_receipt['contractAddress']
print(contract_address)
When I try to verify my contract, I'm asked to provide the source code, the contract name, a compiler version and whether optimization was used.
I use the following for the requested source code
pragma solidity ^0.4.0;
contract Greeter {
string public greeting;
function Greeter() {
greeting = 'Hello';
}
function setGreeting(string _greeting) public {
greeting = _greeting;
}
function greet() constant returns (string) {
return greeting;
}
}
I use Greeter as the contract name. solc --version returns Version: 0.4.24+commit.e67f0147.Darwin.appleclang which I found was committed on May 16: https://github.com/ethereum/solidity/search?q=e67f0147&type=Commits.
I've tried all of the following combinations for compiler version + optimization enabled: {0.4.24, 0.4.24-nightly.2018.5.16} x {optimization enabled, optimization disabled} and none of these combinations worked. I get the following error when I try 0.4.24-nightly.2018.5.16 as the compiler and optimization not enabled.:
The compiled result does not match the input creation bytecode located at 0x4c94e89d5ec3125339906109f143673f40868df2.
Compilation failed: ["Warning: This is a pre-release compiler version, please do not use it in production.\n",":6:5: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use \"constructor(...) { ... }\" instead.\n function Greeter() {\n ^ (Relevant source part starts here and spans across multiple lines).\n",":6:5: Warning: No visibility specified. Defaulting to \"public\". \n function Greeter() {\n ^ (Relevant source part starts here and spans across multiple lines).\n",":14:5: Warning: No visibility specified. Defaulting to \"public\". \n function greet() constant returns (string) {\n ^ (Relevant source part starts here and spans across multiple lines).\n"] .

You should not need compiler parameters in order to verify the contract. Only in rare occasions will you need to know them. I currently use 0.4.21 compiler and was able to verify my contract just with the contract Solidity source code.
I might suggest specifying the specific compiler you are using in your contract pragma, instead of ^0.4.0.
I was also using a Geth PoA environment when I attempted to verify, and had to make a few modifications to your code in order to get this to work. Are you using a Quorum environment? Which protocol?
Here is my code taken from the Quickstart example in the README:
import json
import web3
from web3 import Web3, HTTPProvider
from solc import compile_source
from web3.contract import ConciseContract
from web3.middleware import geth_poa_middleware
# Solidity source code
contract_source_code = '''
pragma solidity ^0.4.21;
contract Greeter {
string public greeting;
function Greeter() public {
greeting = 'Hello';
}
function setGreeting(string _greeting) public {
greeting = _greeting;
}
function greet() public returns (string) {
return greeting;
}
}
'''
compiled_sol = compile_source(contract_source_code) # Compiled source code
contract_interface = compiled_sol['<stdin>:Greeter']
# web3.py instance
w3 = Web3(HTTPProvider("https://YYY:ZZZ#XXXXXX.us-east-2.kaleido.io"))
w3.middleware_stack.inject(geth_poa_middleware, layer=0)
# set pre-funded account as sender
w3.eth.defaultAccount = w3.eth.accounts[0]
# Instantiate and deploy contract
Greeter = w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin'])
# Submit the transaction that deploys the contract
tx_hash = Greeter.constructor().transact()
# Wait for the transaction to be mined, and get the transaction receipt
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
print(tx_receipt.contractAddress)
# Create the contract instance with the newly-deployed address
greeter = w3.eth.contract(
address=tx_receipt.contractAddress,
abi=contract_interface['abi'],
)
# Display the default greeting from the contract
print('Default contract greeting: {}'.format(
greeter.functions.greet().call()
))
print('Setting the greeting to Nihao...')
tx_hash = greeter.functions.setGreeting('Nihao').transact()
# Wait for transaction to be mined...
w3.eth.waitForTransactionReceipt(tx_hash)
# Display the new greeting value
print('Updated contract greeting: {}'.format(
greeter.functions.greet().call()
))
# When issuing a lot of reads, try this more concise reader:
reader = ConciseContract(greeter)
assert reader.greet() == "Nihao"
If you really need to know how to find the compile time arguments, they are typically provided as kwargs to the compile functions. Here's the source line that would do the magic: https://github.com/ethereum/py-solc/blob/c595d84d9f0ef5f5da0a5d79e7d5fcabecfe5f06/solc/main.py#L106

Related

factory contract reverts

I am trying to create a factory contract, which I call DAG:
pragma solidity >=0.7.0 <0.9.0;
import "./Agent.sol";
contract DAG {
address[] agents;
function createDAG() public returns (address) {
// create root agent
address[] memory parentsOfRoot;
address rootAddress = createAgent(parentsOfRoot);
// create child
address[] memory parentsOfChild;
parentsOfChild[0] = rootAddress;
createAgent(parentsOfChild);
return rootAddress;
}
function createAgent(address[] memory _parents) public returns(address) {
Agent agent = new Agent(_parents);
agents[agents.length - 1] = address(agent);
return address(agent);
}
}
It is meant to make something like a connected list of Agents.
pragma solidity >=0.7.0 <0.9.0;
contract Agent {
address[] parents;
constructor(
address[] memory _parents
){
parents = _parents;
}
function getParents() public view returns (address[] memory) {
return parents;
}
}
For some reason, when I call createDAG in the RemixIDE, I get the following error:
transact to DAG.createDAG pending ... transact to DAG.createDAG
errored: VM error: revert.
revert The transaction has been reverted to the initial state. Note:
The called function should be payable if you send value and the value
you send should be less than your current balance. Debug the
transaction to get more information.
Can anyone help me understand why I am unable to call createDAG?
Your snippet is trying to assign into 0th index of the array but this index doesn't exist at that moment. Which throws an "out of bounds" exception.
address[] memory parentsOfChild; // 0 items
parentsOfChild[0] = rootAddress; // trying to assign the first item (index 0)
It's currently (v0.8) not possible to resize in-memory arrays, so you'll need to initialize the array with an already predefined length.
address[] memory parentsOfChild = new address[](1); // 1 empty item
parentsOfChild[0] = rootAddress;
Then you're going to run into another logical error. Function createAgent() is also trying to assign a value to an "out of bounds" index.
When the agents array is empty, this snippet is trying to assign into index -1.
agents[agents.length - 1] = address(agent);
If you want to add a new item to the agents array, you can use the .push() member function of the array.
// instead of `agents[agents.length - 1] = address(agent);`
agents.push(address(agent));

Explicit type conversion not allowed from "int_const" to "contract"

I am trying to deploy a contract from another contract following the example from here
At some point the example states:
Instanciating a new Counter for someone will look like this:
function createCounter() public {
require (_counters[msg.sender] == Counter(0));
_counters[msg.sender] = new Counter(msg.sender);
}
We first check if the person already owns a counter. If he does not own a counter we instantiate a new counter by passing his address to the Counter constructor and assign the newly created instance to the mapping.
However, when I try that in my factory contract:
pragma solidity >=0.7.0 <0.9.0;
contract Factory {
mapping(address => Campaign) _campaigns;
function createCampaign(uint minContrib) public {
require(_campaigns[msg.sender] == Campaign(0));
_campaigns[msg.sender] = new Campaign(minContrib, msg.sender);
}
}
...
contract Campaign {
/* Irrelevant code skipped ... */
constructor (uint minContrib, address creator) {
manager = creator;
minContribution = minContrib;
}
compilation error pops:
from solidity:
TypeError: Explicit type conversion not allowed from "int_const 0" to "contract Campaign".
--> contracts/3_Ballot.sol:10:43:
|
10 | require(_campaigns[msg.sender] == Campaign(0));
| ^^^^^^^^^^^
What comparison is being made here exactly?
require (_counters[msg.sender] == Counter(0));
What is Counter(0)? An instance of contract (like new Counter(0)) or a type conversion of parameter 'int_const' to 'contract'?
Found this this answer which made things a bit clearer.
Apparently this is trying to compare the Contract deployed at address 0 with thatever is stored at _counters[msg.sender] (which I believe should be the address of a deployed contract).
require (_counters[msg.sender] == Counter(0));
With that in mind, I get the error is saying "we're expecting a Counter or address of contract and you give us an int".
I fixed it with Counter(address(0)).

Smartcontract/Lottery : Errors during execution of running scripts

While running the deploy_lottery.py I am getting the following error:
The transactions executes until def start_lottery(). Once it reaches the def enter_lottery the programs stops execution with the following error:
1."sender doesn't have enough funds to send tx."
I am running the script in local development chain with a "id" account.
Can you share your code please? mine looks like this and it works
python
def startLotter():
account = get_account()
lottery = Lottery[-1]
starting_tx = lottery.startLottery({"from": account})
starting_tx.wait(1)
print("The lottery has started!!")
solidity
function startLottery() public onlyOwner
{
require(lottery_state == LOTTERY_STATE.CLOSED, "lottery already open");
lottery_state = LOTTERY_STATE.OPEN;
}
the function only has to change the state of the lottery but that does require a transaction so you should have the funds.

Solidity Internal exception in StandardCompiler

This is the source code
pragma solidity ^0.5.1;
contract myContract{
string value;
constructor() public {
value = "myValue";
}
function get() public view returns(string memory){
return value;
}
function set(string memory _value) public{
value = _value;
}
}
Selected Compiler on Remix IDE is 0.5.1+commit.c8a2cb62
Selected Environment is Javascript VM
When I compile the command I get this error
Internal exception in StandardCompiler::compileInternal: /root/project/libevmasm/ExpressionClasses.cpp(187): Throw in function ExpressionClasses::Id dev::eth::ExpressionClasses::tryToSimplify(const dev::eth::ExpressionClasses::Expression &)
Dynamic exception type: boost::exception_detail::clone_impl<dev::eth::OptimizerException>
std::exception::what: Rule list not properly initialized.
[dev::tag_comment*] = Rule list not properly initial
However this error does not pop up for same source code if I select the compiler as 0.5.11
Other users are saying that they are getting this error on pre 0.5.3 compilers.
This is a bug in a certain version of the compiler - it does not work properly if the javascript runtime environment does not provide enough stack space or memory. It should work with the most recent compilers.
Check this thread for more info

How to return array of struct?

Function getBets() gives me the error: error: Failed to decode output: Error: Unsupported or invalid type: tuple. What am I missing?
pragma solidity ^0.4.11;
contract Casino {
struct Bet {
address by;
uint number;
}
address owner;
Bet[] bets;
event BetPlaced(Bet bet);
function Casino() {
owner = msg.sender;
}
function bet(uint number) {
Bet memory bet;
bet.by = msg.sender;
bet.number = number;
bets.push(bet);
BetPlaced(bet);
}
function getBets() constant returns (Bet[]) {
return bets;
}
function getCount() constant returns (uint length) {
return bets.length;
}
}
At the moment if I'm correct you can't return anything except an array of integers as there is no support for returning multi-dimensional data storages;
You can use an experimental library using:
pragma experimental ABIEncoderV2;
in the place of:
pragma solidity ^0.4.11;
This isn't available on Remix if you're using that at the moment and it's experimental so it may never be part of Solidity source: https://github.com/ethereum/solidity/issues/2948
If you did want to return an array of structs you could convert the whole array to bytes and return the bytes. This would be a bit of an extreme case and I wouldn't advise it.
If you only need to access the method internally and not externally you can pass by storage e.g.
function getBets() internal returns (Bet[] storage _r) {
_v = bets;
}
You may want to switch your struct to another contract. This way you can return an array of addresses. I have found using structs is only useful in storing and retrieving "that" data. Contracts are better to return sets of addresses. Also, I have not used the experimental encoder, so just going off of the current solidity version.