How to test payable/external method with waffle and ethers.js - ethereum

Here is the smart contract, written in vyper, to be tested
owner: public(address)
name: public(String[100])
total_amount: uint256
#external
def __init__(_name: String[100]):
self.owner = tx.origin
self.name = _name
#external
#payable
def donate():
#anyone can donate to the piggy bank
self.total_amount += msg.value
#external
#view
def get_total_amount() -> uint256:
return self.total_amount
What is the right way to test the donate() method of the smart contract with waffle and ethers.js?
Is there a sendTransaction method for ethers.js that can be called on contract's side like in this example of web3+truffle ?

You can use the overrides parameter. It's used after all contract function arguments.
In your case, the contract function has 0 arguments so the overrides is on position 1.
let overrides = {
value: ethers.utils.parseEther("1.0")
};
let tx = await myContract.donate(overrides);
See this issue for more details.

Related

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)).

Call custom Ethereum fallback function with web3.py

I'm trying to implement an upgradable function through delegation. Essentially, the fallback function of contract A is implemented in such a way that when calling function F on contract A, the execution is delegated to function F (same function signature( on contract B.
Callback function looks like this
function() external payable {
address delegate = delegates[msg.sig];
require(delegate != address(0), "Function does not exist.");
assembly {
let ptr := mload(0x40)
calldatacopy(ptr, 0, calldatasize)
let result := delegatecall(gas, delegate, ptr, calldatasize, 0, 0)
let size := returndatasize
returndatacopy(ptr, 0, size)
switch result
case 0 {revert(ptr, size)}
default {return (ptr, size)}
}
}
I ran into problem when trying to use web3.py to call function F in said contract A. I trie a few different things:
// Case 1
Contract.functions.F().buildTransaction()
^ this caused the web3.py to complain that function F is not in contract A's ABI. So then I thought the fallback function uses msg.sig as function signature, so I tried to pass the signature as "data".
// Case 2
Contract.fallback.buildTransaction({'data': "0x61455567"})
// 0x61455567 == bytes4(keccak256("updateContract(address,string,string)"))
which also didn't work because web3.py says "data" cannot be called when building transaction. Finally, I thought I could pass the data field after building the transaction, so I did:
// Case 3
txn_hash = Contract.fallback.buildTransaction({'gas': 1000000})
txn_hash['data'] = "0x837b4bd1"
This time, web3.py didn't complain but the transaction failed on the blockchain (on Rinkeby testnet).
Any help on how to use web3.py to call a custom fallback function?
You can simply use sendTransaction and then it will go into the fallback function.
web3.eth.sendTransaction({'to': contractAddress, 'from': yourAddress, 'data': "0x61455567"})
EDIT:
You can also sign a transaction locally, reference

Solidity error message when executing smart contract: "the constructor should be payable if you send value"

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.

How to determine correct contract compilation options?

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

web3 calls Solidity contract function with extra parameter?

In the http://truffleframework.com/tutorials/pet-shop example, there is the following contract, and the function adopt(uint petId) has only one parameter.
contract Adoption {
address[16] public adopters;
function adopt(uint petId) public returns (uint) {
require(petId >= 0 && petId <= 15);
adopters[petId] = msg.sender;
return petId;
}
function getAdopters() public returns (address[16]) {
return adopters;
}
}
However, in the javascript code app.js, the handleAdopt function call the contract function using the following code.
App.contracts.Adoption.deployed().then(function(instance) {
adoptionInstance = instance;
return adoptionInstance.adopt(petId, {from: account});
})
The function is called with the extra object {from: account}. Why? And is this parameter discarded in the solidity code?
BTW, there is an undefined global variable web3? Is the value be assigned by the MetaMask extension?
That is the transactionObject which describes general information about all transaction calls (gas limit, price, amount of ether to send, etc.). The JS code you posted is using the web3 library. That's not the direct call to the contract API. The web3 library converts it to an RPC. The transactionObject comes after all of the contract parameters. There is another parameter that comes after which is the callback with the results of the contract call (see here).
These are all of the options for the transactionobject described from the docs:
from: String - The address for the sending account. Uses the web3.eth.defaultAccount property, if not specified.
to: String - (optional) The destination address of the message, left undefined for a contract-creation transaction.
value: Number|String|BigNumber - (optional) The value transferred for the transaction in Wei, also the endowment if it's a contract-creation transaction.
gas: Number|String|BigNumber - (optional, default: To-Be-Determined) The amount of gas to use for the transaction (unused gas is refunded).
gasPrice: Number|String|BigNumber - (optional, default: To-Be-Determined) The price of gas for this transaction in wei, defaults to the mean network gas price.
data: String - (optional) Either a byte string containing the associated data of the message, or in the case of a contract-creation transaction, the initialisation code.
nonce: Number - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.