Is it possible to call methods of contract's initializer during its initialization? - ethereum

I tried to deploy following smart contracts
pragma solidity 0.8.17;
contract Contract1 {
constructor() {
new Contract2(address(this));
}
function foo() public pure returns (string memory) {
return "bar";
}
}
contract Contract2 {
Contract1 contract1;
constructor(address _contract1) {
contract1 = Contract1(_contract1);
contract1.foo();
}
}
but it fails with following message:
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.
Seems like it's impossible to call methods of contract's initializer (the contract that created an instance of current one) during its initialization.
My question is how it happens that address of the Contract1 is already exists, but it's impossible to call any of its methods from the constructor of Contract2?

The address of Contract1 is not yet available when the constructor of Contract2 is called. The address of Contract1 is only available after the constructor of Contract1 has finished executing.
This means that the constructor of Contract2 cannot call any methods of Contract1 until after the constructor of Contract1 has finished executing.
In this case you can deploy the Contract1, wait for the tx complete and after deploy the Contract2 using the address of Contract1 in constructor arguments.

Related

How can I do a proxy call on anchor protocol terra ethereum transfer. error: UNPREDICTABLE_GAS_LIMIT

I want to make a smart contract that deposits UST on the eth anchor protocol, by using the deposit function. Here you can find the docs of this function I try to call. https://docs.anchorprotocol.com/ethanchor/ethanchor-contracts/router . The function gets called trough a proxy contract. I found the implementation address by reading the proxy contract on etherscan.
TestContracts on Ropsten testnet:
proxy: 0x7537aC093cE1315BCE08bBF0bf6f9b86B7475008
etherscan: https://ropsten.etherscan.io/address/0x7537aC093cE1315BCE08bBF0bf6f9b86B7475008
implementation (ROUTERV2): 0x2ba0010394eb3e41454c7d79c0fb6e0deb67284b
etherscan: https://ropsten.etherscan.io/address/0x2ba0010394eb3e41454c7d79c0fb6e0deb67284b
I imported the ROUTERV2 contract for calling the proxy with the abi of the implementation.
my execution order is:
deploying the contract
approving the contract for spending the tokens from the sender using ethers.
approveUST function on smart contract (I am not sure if this is necessary)
calling the depositStable function.
I get the following error when calling the depositStale function UNPREDICTABLE_GAS_LIMIT;
Below You see the contract I try to make. It should take the UST of the user and deposit it on eth anchor.
Here is a github link to the hardhat repo of the contract so you can simulate the bug and hopefully help me solving this issue.
https://github.com/tijgersoftware/Terra-anchor
I thank you for taking the time to read my question!
contract Anchor {
address public proxy;
address public operator;
address public USTAddress;
constructor(
address proxy_,
address operator_,
address USTAddress_
) public {
proxy = proxy_;
operator = operator_;
USTAddress = USTAddress_;
}
function approveUST() public {
ERC20(USTAddress).approve(
address(this),
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
);
}
function initDepositStable(uint256 amount) public {
RouterV2(proxy).initDepositStable(amount);
}
function depositUST(uint256 amount) public {
// InterfaceOfImplementationContract(proxyAddress).MethodBeingCalled(
// parameter,
// parameter,
// parameter
// );
ERC20(USTAddress).approve(
address(this),
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
);
RouterV2(proxy).depositStable(operator, amount);
}
}
tags: solidity, smart contracts, ethereum, anchor protocol, terra, brdige trasfer.

Ethereum Transaction Error while calling a contract function from another contract

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;
}
}

In Solidity, can the constructor function have the same name as the contract?

According to this article, the constructor - or initialization - function has the same name as the contract. However, the remix compiler returns an error when I have a function with the same name, saying "defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead."
So, my question is, is using the same name in this situation something that should simply be avoided? (Perhaps it is an out of date practice?)
Since Solidity v0.4.23, constructors are now specified using the constructor keyword:
constructor () {}
Just to compare with the old ways, say we have a Smart Contract called Employee, in the past, you'd specify the contract with its constructor like this:
contract Employee {
// constructor
function Employee() public {
// ...
}
}
But the acceptable way to specify the Employee Smart Contract now is:
contract Employee {
// constructor
constructor() public {
// ...
}
}
Using the name of a contract as its constructor is now deprecated.

Calling External Contract throws error : VM Exception while processing transaction: revert

I've deployed the ScoreStore contract to test RPC, and it works fine. This is ScoreStore contract:
pragma solidity ^0.4.4;
contract ScoreStore
{
mapping(string => int) PersonScores;
function SetScore(string name, int score) {
if(PersonScores[name]>0){
throw;
}
else{
PersonScores[name] = score;
}
}
function GetScore(string name) returns (int){
return PersonScores[name];
}
}
Now I want to use this contract on another contract named MyGame, the contract code is as follows:
pragma solidity ^0.4.4;
contract IScoreStore{
function GetScore(string name) returns (int);
}
contract MyGame{
function ShowScore(string name) returns (int){
// Interface takes an address of the existing contract as parameter
IScoreStore ss = IScoreStore(0x6c38cfb90e8fb1922e61ea4fbe09d29c7751bf82);
return ss.GetScore(name);
}
}
When I give this command on truffle console, mg.ShowScore.call("Anna")
it thorws this:
Error: VM Exception while processing transaction: revert
at XMLHttpRequest._onHttpResponseEnd (C:\Users\Fariha.Abbasi\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2\lib\xhr2.js:509:1)
at XMLHttpRequest._setReadyState (C:\Users\Fariha.Abbasi\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2\lib\xhr2.js:354:1)
at XMLHttpRequestEventTarget.dispatchEvent (C:\Users\Fariha.Abbasi\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2\lib\xhr2.js:64:1)
at XMLHttpRequest.request.onreadystatechange (C:\Users\Fariha.Abbasi\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3\lib\web3\httpprovider.
at C:\Users\Fariha.Abbasi\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\truffle-provider\wrapper.js:134:1
at C:\Users\Fariha.Abbasi\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3\lib\web3\requestmanager.js:86:1
at Object.InvalidResponse (C:\Users\Fariha.Abbasi\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3\lib\web3\errors.js:38:1)
Any idea, what i am doing wrong?
Any help is appreciated, P.S: testrpc is already running.
I was able to compile both the contracts in remix and call the ShowScore function after setting some value from ScoreStore contract successfully.
Are you sure the address given to the interface is correct? Because I got the same revert error when I gave an invalid address.

Calling external contract from a contract in same block

Please check this code:
contract Token is StandardToken {
function transfer(address _to, uint256 _value) public returns (bool success) {
return super.transfer(_to, _value);
}
}
contract CrowdSale {
token = Token(:address)
function buyToken() payable {
token.transfer(beneficiary,tokenAmount); // OPERATION A
anotherAddress.transfer(msg.value); // OPERATION B
}
}
In the above example, will OPERATION A and OPERATION B be called in same block?
Or buyToken will be called which calls token.transfer and wait till it is mined and then anotherAddress.transfer is called in next block once first is mined?
I think you are mistaken about some concepts here. A block registers transactions.
The transaction is the fact of calling a method, deploying a contract, "moving the state of a contract".
In simple words : yes, a contract called by another contract will be called in the same block as the block won't contain the instructions itself but the result of the transaction .
In order to be able to give the result of a transaction, by logic, the whole instructions need to be processed on same block, otherwise the miner couldn't determine if the transaction is valid and then register it into the block.