web3 calls Solidity contract function with extra parameter? - ethereum

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.

Related

Can ETH miners check all the data which is stored in Ethereum?

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

Aave aaveLendingPool.withdraw() return value validation

I am writing a pull payment function and, as with any external call it is good practice validate the result and check successful execution. I am using the following interface:
interface IAaveLendingPool {
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
function withdraw(
address asset,
uint256 amount,
address to
) external;
function getReservesList() external view returns (address[] memory);
}
aAveLendingPool= IAaveLendingPool(0x0543958349aAve_pooladdress)
The interface provided by Aave doesn't specify a return either. The withdraw function of the LendingPool.sol contract returns external override whenNotPaused returns (uint256).
The question: Can I use the returned uint to validate successful execution or aAveLendingPool.withdraw() returns a boolean? Will the following work as expected?
///#notice assigns dai to caller
require( aaveLendingPool.withdraw(
address(dai),
amount,
msg.sender), "Error, contract does not have enough DAI")
Please provide a solidity docs link to external function call return value, if any.
According to the Consensys Diligence Aave V2 audit:
ERC20 implementations are not always consistent. Some implementations of transfer and transferFrom could return ‘false’ on failure instead of reverting. It is safer to wrap such calls into require() statements to these failures.
Therefore, wrapping the transfer call in a require check is safe and sufficient.
require( aaveLendingPool.withdraw(
address(dai),
amount,
msg.sender), "Error, contract does not have enough DAI")

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 sign a transaction send by contract

I am trying to understand the basics behind signing an ethereum transaction.
I come across Gnosis's MultiSigWallet :
https://github.com/gnosis/MultiSigWallet/blob/master/contracts/MultiSigWallet.sol
In which, a modifier onlyWallet requires a transaction must be sent from the contract itself, but the transaction is signed by one of the owners of the contracts:
modifier onlyWallet() {
require(msg.sender == address(this));
_;
}
for functions like:
function replaceOwner(address owner, address newOwner)
public
onlyWallet
ownerExists(owner)
ownerDoesNotExist(newOwner)
{...}
I have successfully deployed the contracts on my testnet, and tried its functionalities using their dapp https://wallet.gnosis.pm/#/transactions
However, I cannot understand how a transaction is signed and sent to meet the onlyWallet requirement, since signing a transaction using metamask for example will cause the msg.sender to be my own wallet address.
If possible, an example of this ethereumjs-tx's functions would be much appreciated.
like:
const privateKey = Buffer.from('<private key 1>','hex');
const txParams = {
nonce: web3.utils.toHex(11),
gasPrice: web3.utils.toHex(1000000000),
gasLimit: web3.utils.toHex(300000),
to: '<contract address>',
value: web3.utils.toHex(web3.utils.toWei("1",'ether')),
data: '0x00',
chainId: 1
};
let tx = new EthTx(txParams);
tx.sign(tx.serialize().toString('hex');
web3.eth.sendSignedTransaction(`0x${tx.serialize().toString('hex')}`,
(error, data) => {
if(!error) {
console.log(data);
}else console.log(error);
}
);
Thank you very much
Adding and removing an owner follows the same rules as confirming any transactions from the MultiSigWallet. Assume the wallet was deployed with 3 EOA addresses as owners and requiring 2 confirmations for execution. For any regular transaction, say donate funds from the wallet to a FundRaisingContract, one of the owners would need to first call submitTransaction() passing in the address of FundRaisingContract, the amount of ether, and the hash for the donate function. After submission, you still need 1 of the other owners to confirmTransaction (the submitter is automatically confirmed). Once completed, now executeTransaction can be successfully run which will execute the call to donate() from the MultiSigWallet address.
That last part is what you're looking for to answer your question. To add an owner, repeat the example but use the MultiSigWallet address and the hash of the addOwner method. When one of the other owners confirms the transaction, addOwner will be called and it will pass the onlyWallet modifier check.

Creating instance of contract inside another contract and calling it's methods results in thrown exception

I have 2 basic contracts: one is for token and the second is for sale.
Token сontract:
contract MyToken is StandardToken, Ownable {
string public constant name = "My Sample Token";
string public constant symbol = "MST";
uint32 public constant decimals = 18;
function MyToken(uint _totalSupply) {
require (_totalSupply > 0);
totalSupply = _totalSupply;
balances[msg.sender] = totalSupply;
}
}
Sale Contract
contract Sale {
address owner;
address public founderAddress;
uint256 public constant foundersAmount = 50;
MyToken public token = new MyToken(1000);
uint256 public issuedTokensAmount = 0;
function Sale() {
owner = msg.sender;
founderAddress = 0x14723a09acff6d2a60dcdf7aa4aff308fddc160c;
token.transfer(founderAddress, foundersAmount);
}
function() external payable {
token.transfer(msg.sender, 1);
owner.transfer(msg.value);
}
}
StandardToken and Ownable are all standard implementations from OpenZeppelin repository. Full contract source is available here.
So basically in my Sale Contract I create an instance of my token contract with fixed supply and assign all of the tokens to the caller. Then I transfer some amount of tokens to founder address. When I try to send some ethereum to Sale contract I'm attempting to transfer some of my tokens to the sender (Running all code in Remix browser, I create an instance of Sale contract and call "fallback" method specifying some ether amount). However, this fails with "Exception during execution. (invalid opcode). Please debug the transaction for more information." message. All that I can see when debugging is that code fails in payable method at line:
token.transfer(msg.sender, 1);
I can't see the exact reason for this as I'm not able to step into this method and see whats going on inside.
Interesting thing is that when I remove a call to transfer method on token instance in Sale Contract constructor - code seems to run fine without any exceptions.
What am I missing?
I debugged into the the contract using remix, and the invalid opcode is thrown by:
290 DUP8
291 DUP1
292 EXTCODESIZE
293 ISZERO
294 ISZERO
295 PUSH2 012f
298 JUMPI
299 PUSH1 00
301 DUP1
302 INVALID
I left out the rest, but essentially it loads the address of the token contract and calls EXTCODESIZE which retrieves the contracts code size, and checks that it's not equal to 0 (the token contract exists), unfortunately, it did equate to 0. At this point, I'm unsure whether this is a limitation in remix or I've misunderstood the setup.
I tried the identical contract setup on truffle + testrpc and it deployed, accepted the currency successfully. Do note however that testrpc indicated:
Gas usage: 59137
Meaning that this is above the default sendTransaction w/ no data default (21,000 gas). This means that in a live environment, ensure that you inform users to include extra gas, otherwise the fallback function would probably fail due to OOG errors.
The reason behind this is that you're using a fallback function. Try using a normal function and it should happen.