Ethereum Transaction Error while calling a contract function from another contract - ethereum

Following smart contract works fine in Remix and Ganache. However doesn't work on private ethereum blockchains like Kaleido or Azure. What am I missing. When I call setA it consumes all gas and then fails.
pragma solidity ^0.4.24;
contract TestA {
uint public someValue;
function setValue(uint a) public returns (bool){
someValue = a;
return true;
}
}
contract TestB {
address public recentA;
function createA() public returns (address) {
recentA = new TestA();
return recentA;
}
function setA() public returns (bool) {
TestA(recentA).setValue(6);
return true;
}
}

I tried your contract in Kaleido, and found even calling eth_estimateGas with very large numbers was resulting in "out of gas".
I changed the setValue cross-contract call to set a gas value, and I was then able to call setA, and estimating the gas for setA showed just 31663.
recentA.setValue.gas(10000)(6);
I suspect this EVM behavior is related to permissioned chains with a gasprice of zero. However, that is speculation as I haven't investigated the internals.
I've also added eth_estimateGas, and support for multiple contracts in a Solidity file, to kaleido-go here in case it's helpful:
https://github.com/kaleido-io/kaleido-go
Another possibility for others encountering "out of gas" calling across contracts - In Geth if a require call fails in a called contract, the error is reported as "out of gas" (rather than "execution reverted", or a detailed reason for the require failing).

You are hitting the limit of gas allowed to be spent per block. Information about gas limit is included into every block, so you can check what's this value is right now in your blockchain. Currently on Ethereum MainNet, GasLimit (per block) is about 8 millions (see here https://etherscan.io/blocks)
To fix this, you can start your blockchain with modified genesis file. Try to increase value of gasLimit parameter in your genesis file, which specifies the maximum amount of gas processed per block. Try "gasLimit": "8000000".

Try to discard the return statement of setValue method in contract TestA.
pragma solidity ^0.4.24;
contract TestA {
uint public someValue;
function setValue(uint a) public {
someValue = a;
}
}

Related

How to retrieve data from a SmartContract that is not listed in their ABI

I'm trying to retrieve the total supply of an ERC1155 SmartContract. This code was made by my friend and has been deployed. He took the code from OpenZeppelin with Burnable and Pausable presets.
The function totalSupply that I am trying to retrieve exists in the code. But, when I see the ABI, the totalSupply does not included.
(Sorry for small screenshot. Please see this screenshot in the new tab)
MyErc1155Contract compiled
This is where to get the ABI
Full code is here: click_this_to_go_to_pastebin
Then I am trying to write smartcontract to retrieve the totalSupply;
pragma solidity ^0.8.0;
contract TotSup {
uint256 public hasilBal;
uint256 public hasil;
function balanceOf(address erc1155_address,
address user_address,
uint256 nft_id) public {
(bool successA, bytes memory resultA) =
erc1155_address.call(abi.encodeWithSignature(
"balanceOf(address,uint256)",
user_address,
nft_id
));
hasil = abi.decode(resultA, (uint256));
}
function bal(address erc1155_address, uint256 nft_id) public {
(bool successA, bytes memory resultA) =
erc1155_address.call(
abi.encodeWithSignature("totalSupply(uint256)", nft_id
));
hasilBal = abi.decode(resultA, (uint256));
}
}
I test my idea with writing another function balanceOf and it works perfectly.
And for the totalSupply in function bal is fail.
Is it possible to retrieve or calling function which is not included in the ABI? If yes, how to achieve that? And last, why call balanceOf still need for paying gas for just retrieving the data?
When a function exists in the code when you compile the code it reflects in the ABI, Without the function signature, you can't call the function.
As for your second answer, balanceOf in TotSup will cost you gas as it is not a view function.

Managing gas fees in solidity smart contract

I have a ERC20 smart contract with edited transfer function
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
if(_transactionMaxValue > 0){
require(_transactionMaxValue >= amount, "You can not transfer more than 1000000 tokens at once!");
}
transfer(recipient, amount);
}
I have added if statement in transfer function, in case user indicates limit per single transaction before deploying. I was wondering if this would affect gas fees when transferring tokens, in order to decide weather to leave the "universal" ERC20 smart contract template with indictable transaction limit or compose new one, with no if statement, if no transaction limit was indicated.
I was wondering if this would affect gas fees when transferring tokens
Adding the (if and require) conditions increases the total amount of gas used, but the increase is small in the context of gas usage of other operations of the parent transfer() function. It's because in the overriding function, you're performing "just" one more storage read and few other operations in memory.
Execution of your transfer() function costs 54,620 gas (including the parent function; assuming the require() condition doesn't fail). While execution of just the parent transfer() function costs 52,320 gas.
You need to use super.transfer(recipient, amount); if you want to invoke the parent transfer() function. Without the super keyword, you'd lock the script in an infinite recursion, always invoking itself.
Also, in order to correctly override the parent function, you need to state the override modifier (and virtual if you are planning to override this function as well) before the public visibility modifier, and to return the value as declared.
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
uint256 _transactionMaxValue = 1000000;
constructor() ERC20("MyToken", "MyT") {
_mint(msg.sender, 1000000);
}
// moved the `override virtual` before the `public` modifier
function transfer(address recipient, uint256 amount) override virtual public returns (bool) {
if(_transactionMaxValue > 0){
require(_transactionMaxValue >= amount, "You can not transfer more than 1000000 tokens at once!");
}
// added `return super.`
return super.transfer(recipient, amount);
}
}
Everything #Petr Hejda suggested is correct.
Additional improvement here would be to make a require statement fail reason string smaller and more precise, as it will result in the smaller bytecode, and therefore cheaper deployment.

How to fix "Gas estimation failed error" when transferring Minter and Owner roles to a new account in one function?

I have a simple ERC20 contract which is ERC20Detailed, ERC20Mintable and Ownable. On deployment I want:
Add Minter to a new account, passed in the argument
Remove deployer from Minter role
Transfer Ownership to a new account, passed in the argument
Same actions I have declared in another function called transferRights()
The problem is that I am getting "Gas estimation failed error", which isn't because I don't have enough gas, but there might be a bug in the code. If I remove first two (addMinter, renounceMinter) actions, then it's all good (No warning).
I have deployed this contract on Ropsten, where I was getting same error in the beginning, but by commenting first two actions and adding them again transaction went through without any warning and Contract works as it supposed to be.
pragma solidity ^0.5.0;
import "github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol";
import "github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol";
import "github.com/OpenZeppelin/openzeppelin-solidity/contracts/ownership/Ownable.sol";
contract MyToken is ERC20Detailed, ERC20Mintable, Ownable {
uint256 private msgCount;
address constant ETHER = address(0);
mapping(uint256 => string) private message;
constructor(string memory name, string memory symbol, uint8 decimals, address _newOwner) ERC20Detailed(name, symbol, decimals) public {
addMinter(_newOwner);
renounceMinter();
transferOwnership(_newOwner);
}
function doMint(uint256 _amount, address _beneficiary1, address _beneficiary2, address _beneficiary3) public onlyOwner {
require (_amount >= 0);
require(_beneficiary1 != ETHER && _beneficiary2 != ETHER && _beneficiary3 != ETHER);
require(mint(_beneficiary1, _amount.mul(20).div(100)));
require(mint(_beneficiary2, _amount.mul(30).div(100)));
require(mint(_beneficiary3, _amount.mul(50).div(100)));
}
function setMessage(string memory _message) public onlyOwner {
message[msgCount] = _message;
msgCount = msgCount.add(1);
}
function readMessage(uint256 _msgId) public view returns(string memory) {
return message[_msgId];
}
function transferRights(address _newOwner) public onlyOwner {
addMinter(_newOwner);
renounceMinter();
transferOwnership(_newOwner);
}
}
I can still send a transaction and deploy I guess (as mentioned above I did it on testnet), even though it is saying "The transaction execution will likely fail", but I want to make sure that code is bug free. Any feedback would be greatly appreciated. Thanks!
UPDATE
Problem found! In the constructor I was passing the same account address as I was using for deploying. Thus, it resulted adding the Minter role to myself, which I already had.

Unable to match calculated "gas used" value using Solidity IDE to the etherscan explorer "Gas Used By Transaction"

I am trying find the gas used by the transaction when a method is clicked in the remix solidity IDE. my code is as below. Value I am getting in the gasUsed variable is different to the value that is being shown on the etherscan explorer for this transaction. It would be helpful if someone helps me in correcting my code.
pragma solidity ^0.4.22;
contract id{
uint public id;
uint public senderValue;
uint256 public gasUsed;
constructor() public {
senderValue= msg.sender;
}
function setId(uint _id) public {
uint256 gasInitial = gasleft();
id= _id;
setGasUsed(gasInitial - gasleft());
}
function setGasUsed(uint256 _gasUsed) private {
gasUsed = _gasUsed;
}
}
The value of "gas used" in remix IDE is Execution Cost and the value of "Gas Used By Transaction" in etherscan is "Transaction cost".
Execution Costs are based on the cost of computational operations which are executed as a result of the transaction.
Transaction Costs are always based on the cost of which type of data you will send to blockchain. This depends on,
base cost of transaction (21000 gas)
the cost of a contract deployment (32000 gas)
the cost for every zero byte of data or code for a transaction.
the cost of every non-zero byte of data or code for a transaction.
You can understand easily by this image
Hope this answer clear your doubt.

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.