I want to write a library which can be callcalled by any contract.
As part of this, I want to write a function which returns the contract address of the library to the contract which callcalled it.
address(this) is normally the solution, but in the case of callcode, it can only be used to check if the contract is being callcalled through if(address(this)==msg.sender) which become always true.
So how to perform this without having to rewrite the code each time because of the requirement to predict the future library’s contract address ?
Related
I'm debugging a reverted transaction on Polygon and this is all the information I have: https://mumbai.polygonscan.com/tx/0xfa86dc4957e3a3da9298b7672b11a20ebe921854fa494dc073920c067c1e693f#internal
If I'm reading it correctly, it seems to be saying that a CREATE2 reverted. But what are some reasons why a CREATE2 can revert? I'm aware that it would revert if something already existed at the address, but this isn't the case here, as you can see from here: https://mumbai.polygonscan.com/address/0x6bb03ca906c0372f384b845bd5ce9ca4327ffbe6
The linked transaction makes a message call (aka internal transaction) to contract deployed at 0x1079b7398b6efd9845c4db079e6fac8d21cf67b3.
This 0x1079b7... contract then tries to deploy a new contract on address 0x6bb03ca906c0372f384b845bd5ce9ca4327ffbe6, you can see the bytecode of the new contract for example in the Tenderly debugger.
As far as I'm aware, create2 can revert for 3 reasons:
Not enough gas left to perform the deployment
Not an issue in this case. Acording to the debugger there was ~9M gas units left and the deployment would take only ~1M gas units.
Deploying contract to address where another contract instance is already deployed.
Because you can predetermine the contract address with create2, this can happen. However not in this case either, the 0x6bb03c... address is empty, there's no contract deployed.
So we're left with uncaught exception during executing the constructor.
pragma solidity ^0.8;
contract MyContract {
constructor() {
require(false);
}
}
A code like this fails the deployment and effectively causes the create2 code to revert.
Unfortunately, without the new contract source code, it's hard to tell what exactly is the cause of constructor revert. Whether it's unexpected length or input params to the constructor, logical error, trying to make a call to non-existing contract, or anything else.
It turns out that I'm misreading Polygonscan and that just because there's a red mark next to an internal transaction doesn't mean that it's the internal transaction itself that reverted; it means that the whole transaction reverted. Anyways, using the Tenderly debugger helped me identity the real bug.
What is the best architecture to allow users to deploy their own smart contracts (NFT collections), and still be able to index the tokens created on those dynamically created contracts using something like The Graph subgraphs?
Currently the idea was to have a "Factory" contract deployed by me, so easily indexable, and inside that have a function createCollection that will deploy a contract using the new <ContractName> keyword.
Is this bad architecture? Would this even work?
The end goal is to allow users to deploy contracts from a UI, but still be able to listen for their events through my parent contract, so that I can index everything in a subgraph.
What you can actually do is to save a pointer to the parent contract into each generated contract. Thus, whenever you have an event you want to store into the parent contract, you can maybe interact with a function in it. But you may also want some type of verification to ensure that only child contracts can call the parent functions and not external contracts, so maybe you could make a mapping indexing the address of the generated child contracts, which will be able to call functions from the parent. What you can not do is to make the parent automatically look for events on the child's contracts.
Hope you find this information helpful :)
I am trying to save a variable that gets emmited by an event, from a function in another smart contract, that I’m calling, into a storage variable within my smart contract.
So my call looks something like this:
ExternalContract.foo(boo);
The event in ExternalContract that contains the desired variable:
emit Event(bytes desiredVariable)
So I want to save this variable in my contract without relying on an off-chain script. Is there even a way to do it?
The Log and its event data is not accessible from within contracts (not even from the contract that created them).
Source: https://docs.soliditylang.org/en/v0.8.7/contracts.html#events
So unless there's a getter function for the desiredVariable, or unless it's stored in a public property (they have automatically generated getter functions as well), there's no way to get the event log value from a contract, and you'll need to use an off-chain app.
I am new to solidity, but checking through a specific contract I found the following line of code in the IERC20 declaration:
IERC20 public "TOKEN NAME" = IERC20("THE ADDRESS OF ANOTHER CONTRACT");
This code was found in a contract that is effectively a fork of another project, but the developers say they are unrelated. Of course, people are just FOMO into the token - I know this forum here is not for this type of discussion so I'll abstain from the same.
However, from a solidity coding perspective, why would one write this line of code directly referencing another contract address (the forked address) when making the IERC20 declaration - what does this do, is there a purpose to this?
It seems to me that this is easier and more reliable. Alternatively, you can pass this address in constructor parameters, or provide a special method to set it.
The IERC20 is an interface that defines expected functions arguments and return values.
It helps validating whether the caller is passing correct data types, amount of arguments, and helps parsing the returned data to expected types.
Let's show it on a very simple interface
interface IGame {
function play(uint256 randomNumber) returns (bool won);
}
Elsewhere in your contract, you define a variable that uses this interface
IGame game = Game("0xthe_game_address");
You can then directly call the other contract's methods defined in the interface and pass the return values to your variables.
bool didIWin = game.play(1);
The call would fail if the game contract didn't have the play method or didn't return any value (plus in few other cases).
As for why is the address hardcoded, it's probably just to simplify the development as Mad Jackal already said in their answer.
One more plausible reason in some cases is to gain more trust by showing users that the contract admins are not able to cheat you by changing the destination address (possibly to a contract made by them doing whatever they want).
Edit: If the another contract's address is really unrelated and useless (meaning, the fork is not calling it), it's probably just a human error and the developer forgot to remove it.
it is deployed into node by using testrpc it not working in that node especially transferto function and the withdrawal function.how to fix this problem.it's only working in compiler version:0.4.25+commit.59dbf8f1.Emscripten.clang, it's working in higher version of compiler.
The reason why it could be working in higher versions is because you have constructor() function. If you want to have this contract work for previous versions create the constructor function as function ethertransfer() also when you have revert errors most probably it will happen because the conditions you have written in require() statements. Require Statement also accept second parameter a string which you can put description. Check all require statements carefully, another option I would highly suggest is use remix browser ide. There you can debug through the debug tool in that it will help you step in and step over the transaction flow. So that at the end it will be very easy to identify the root cause of the issue.
It seems code is fine,
Make sure that contract has some ethers on balance require(address(this).balance >= amount);
and you calling these functions from owner address require(msg.sender == _owner);
If you use solidity version >= 5.0.0, use withdrawal pattern https://solidity.readthedocs.io/en/v0.5.0/common-patterns.html#withdrawal-pattern