Whose gas is consumed for indirect contract's function call? - ethereum

i'm working on solidity for Dapp dev.
Let me assume this situation below, with 2 contracts, A and B.
contract A {
B contract_b;
constructor(address b_addr) {
contract_b = B(b_addr);
}
function pass() public {
contract_b.do_sth();
}
}
contract B {
constructor(address b_addr) {
//
}
function do_sth() external {
// do something state-changing stuffs //
}
}
I vaguely noticed that view function does not spend gas,
so if do_sth() is view function, then nothings' bothering.
but with debugging, i found that in processing do_sth() invoked by pass(),
msg.sender becomes the constact address of A, not the original sender.
which means, in do_sth() scope, msg.sender is changed.
Then, whose gas will be consumed for do_sth() process?

Each Ethereum transaction has a gas attached to it and only this gas can be spent during the processing of the transaction. Any contract calls count against the original transaction and contracts cannot pay the gas fee themselves.

Related

What is the mechanics behind this below update contract balance

In below function, how the contract balance is updated by just assigning the msg.value into deposit parameterized variable?
function transferToContract(uint256 deposit) public payable {
require(msg.value == deposit);
deposit = msg.value; //how it works?
}
I'm trying to find answer about behind the mechanics of the above code.And I'm expecting the precise and to the point answer of this.
SInce your function is marked as payable you can send money when you call this function. If you develop an app on Remix, after you deploy the contract, you would have an inbox next to the function to enter the amount. Or if you are interacting with the contract on front-end, you might have a function like this
await contract.methods.contribute().send({
from: accounts[0],
value:1000000,
});
the value that you are sending to the contract will be available to the contract as msg.value.

How to use your own tokens in other contracts?

so I created a token tokenA
contract tokenA is ERC20 {
address public deployer; //to save adress of the deployer
constructor() ERC20('tokenA', 'TA') { //called by the deployer (once)
_mint(msg.sender, 1000000000000 * 10 ** 10); //mint/create tokens - we have created 100000000000*10^18 tokens
deployer = msg.sender; //set the deployer
}
//total supply is fixed no more can be created ever
function burn (uint amount) external { //remove tokens by sending then to a zero address
_burn(msg.sender, amount);
}
}
and I have deployed them onto the Rinkeby (4) injected web3 environment.
now I have to use these tokens as price for purchasing an NFT (which I also have to make)
so how do I use them in my code?
I can use ether like
uint price = 0.005 ether;
and the compare the transferred value with this, but if I write
uint price = 0.005 tokenA;
it gives an error, even though I have deployed tokenA and it resides in my meta mask acc
uint price = 0.005 ether; this is correct.
But inside your function to buy an NFT you need:
Remove the payable keyword.
Add the transferFrom function of the ERC-20 token in order to transfer price (0.005e18) tokens to the recipient address you specify.
Keep in mind that in order to successfully call the transferFrom function the user first need to call the approve function.
For a more in dept explanation i suggest to read the OpenZeppelin ERC-20 docs/github repo

No values being returned

Exploring blockchain using Ethereum and solidity via Remix and I encounter this code:
pragma solidity ^0.8.1;
contract AccountsDemo{
address public whoDeposited;
uint public depositAmt;
uint public accountBalance;
function deposit() public payable{
whoDeposited = msg.sender;
depositAmt = msg.value;
accountBalance += address(this).balance
}
}
According to the book I'm using, calling deposit should result in accountBalance and depositAmt being increased. When I try, nothing happens. The transactions are recorded on the blockchain but no increase happens. The book uses an older version of solidity - 0.6.0 not sure if this is the cause of my frustration.
Any idea what I'm missing here?
What your current deposit function does:
whoDeposited = msg.sender;
Stores the sender address to property whoDeposited. Mind that the value of whoDeposited is overwritten every time you execute the deposit() function.
depositAmt = msg.value;
Stores the transaction value to property depositAmt. Mind that the value of depositAmt is overwritten every time you execute the deposit() function.
accountBalance += address(this).balance
Increments value of property accountBalance by current contract balance. The current contract balance (address(this).balance) already reflects the transaction value that was send while executing the deposit() function.
So if your contract already had balance of 10 wei, accountBalance was 10, and now you were sending 2 wei... During the execution, address(this).balance is now 12 (because of the 2 wei that you're sending), and then accountBalance += 12, which is a result you don't want.
By the way, your snippet has a syntax error and it wouldn't compile because of the missing semicolon at the end of line.
To achieve your goal - store the current contract balance in both depositAmt and accountBalance (so they are always going to have the same value, also same as address(this).balance), you can do this:
depositAmt += msg.value;
accountBalance = address(this).balance;
I switched the += and = operators. So now, when you send a value to your deposit() function:
whoDeposited = msg.sender;
The behavior stays the same as described above.
depositAmt += msg.value;
Every time you execute the deposit() function, the value of depositAmt increments by the value of the transaction. Which effectively reflects the current balance of your contract.
accountBalance = address(this).balance;
Every time you execute the deposit() function, the value of accountBalance is set to the current contract balance. The current contract balance already reflects the value you sent in the current transaction.
Note: I used the word "always" few times in this answer. It's not really always - there are some edge cases like funding your contract address from a selfdestruct function or prior to the contract deployment, where the address(this).balance is going to be different from your depositAmt and accountBalance. But most likely, you're not going to meet these edge cases in the beginning, so you can consider it "always" for now. It's just good to know that there are cases where this snippet won't work as expected.

why is my withdraw function consuming infinite gas? it's a fairly simple function

it's my first ever solidity contract and i can't figure out why my withdraw function is consuming infinite gas. when i compile the contract it gives a warning.
Gas requirement of function Faucet.withdraw(uint256) high: infinite.
If the gas requirement of a function is higher than the block gas limit, it cannot be executed. Please avoid loops in your functions or actions that modify large areas of storage(this includes clearing or copying arrays in storage)"
pragma solidity ^0.5.11;
//Our First Contract is a Faucet
contract Faucet
{
//Deposits ethers
function deposit(uint256 amount) payable public {
require(msg.value == amount);
// nothing to do!
}
//Give out ether to anyone who asks
function withdraw(uint256 withdraw_amount) public
{
if(withdraw_amount <= address(this).balance)
{
//Send the amount to address which requested it
msg.sender.transfer(withdraw_amount);
}
}
}
Note: i have successfully deployed the contract but transactions are failing because they run out of gas. is it due to this warning ?
UPDATE
If you want to send ether to a contract without calling any of its functions, you need to have a fallback function in that contract.
Add this function in the contract:
function () external payable {}
The code looks fine.
I also didn't encounter any problems when actually running your code.
Sometimes error messages are not accurate. Maybe you call withdraw with value?
You can use remix to test it.

Does solidity optimize gas usage based on total storage used before and after a contract method is called?

Here is a simple contract to demonstrate what I am asking:
contract Example {
uint256 intOne;
uint256 intTwo;
function test1()
public
payable
{
intOne = 300;
}
function test2()
public
payable
{
intOne = 0;
intTwo = 300;
}
}
After freshly deploying the contract, I first called test1() and it used 41527 gas.
This made sense to me since writing intOne from zero to non-zero will use 20,000 gas, plus base line gas usage (however that works).
I then called test2 which surprisingly used only 31453 gas.
Shouldn't changing intOne from non-zero to zero cost 5000, then another 20,000 to change intTwo from zero to non-zero?
Or is solidity able to calculate the difference in total storage used before and after the transaction to determine the amount of gas used?
Answer found in question https://ethereum.stackexchange.com/questions/32419/is-refunded-gas-for-freed-storage-given-to-the-contract-the-allocator-or-t
I was not aware of gas being refunded for zeroing out a word.