Solidity: Constructor function needs to be always "public"? - constructor

In solidity, while relating a "withdraw" function to be only callable from the admin contract, the "construct" comes handy.
address public owner;
constructor() public { owner =msg.sender;}
Question: How come it has to be set as a "public" function? As we want no one but us to trigger the withdraw, shouldn´t it be entered as "internal" or "private"?

the constructor is just triggered on deploy so no one else can call it before the deploy, it can be public and you will have no problems but in most recent solidity versions is not necessary to mark the constructor as public

A withdraw function should be marked as public or external for you, or its non-contract owner, to be able to withdraw it. Why? If you mark a function as private, only the functions inside the smart contract will be able to interact with it, and by marking a function as internal, functions inside a contract and contracts that inherit from this one will be able to call the function. Why you probably want to make it this way? Because you, as a normal user, wont be able to call this function directly. So by making this function public or external, every user will be able to interact with the function. And here is your question.
How come it has to be set as a "public" function? As we want no one but us to trigger the withdraw, shouldn´t it be entered as "internal" or "private"?
You can set the function as public and create a require statement (it can be a modifier or a conditional "if", as you want.) and just check if the remitent is the owner. And only if it is, then withdraw. Here is an example:
function withdraw() public {
require(msg.sender == owner, "Only the owner can call this function.");
// Withdraw logic here.
}
Hope you find this useful :)

Related

How can I combine 2 smart contract functions in one transaction?

I am building two smart contracts, one is casino contract and the other one is lottery contract(planning to deploy it separately). I want to combine both the placebet(casino) function and buyticket(lottery) function in one call. Once user would call placebet on casino contract, he will automatically buys lotteryticket also. Any help will be appreciated. Thank you.
Note: (Pls. respect) I am just a newbie, no formal coding education, I am just studying how to make dapp.
If I understand correctly, you need to make the first method call another method from another contract.
Here is an example:
contract LotteryContract {
function buyTicket() public {
// code to buy ticket
}
}
contract CasinoContract {
function placeBet() public {
// code to place bet
LotteryContract.buyTicket()
}
}
The basic idea in this example is that we call the LotteryContract's method in CasinoContract. In this case, when the user makes a bid via the placeBet method, the contract will call another buyTicket method
If you meant to make two calls to different contracts at once from the user, you can't do that. The user can only call one method from the contract, which will call other methods inside itself.

Get error "Derived contract must override function _beforeTokenTransfer"

I want to implement a burn feature in my ERC721 contract in Solidity. To do so, I have imported the function burn from ERC721Burnable.sol.
Since I have imported it I get the following error:
"Derived contract must override function _beforeTokenTransfer".
The same goes with supportsInterface function.
I did override both of them as you can see below. It works but I would like to understand why do I have to do that?
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
I checked Openzeppelin repo, _beforeTokenTransfer is called inside _burn function. At first, I thought it was the main reason but the fact is that _beforeTokenTransfer is also called inside mint and I did not have that error before.
I have no idea why I have to override supportsInterface.
Thanks
ERC721Burnable inherits from two contracts:
abstract contract ERC721Burnable is Context, ERC721 {}
ERC721.sol contract has _beforeTokenTransfer and _afterTokenTransfer unimplemeted functions. you have to implement those in your contract.
from this github issue
ERC721Enumerable and ERC721Burnable both override the
_beforeTokenTransfer and supportsInterface functions. Solidity requires you to "fix" that overriding conflict. If we were able to
address that in our contract we would, but its a solidity requirement
that the child contract explicitly resolves this.
Looks like you 2 of contracts are conflicting inhering supportsInterface

Saving external event variable into smart contract storage variable

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.

Add custom field when mint new ERC721 token

i'm using the ECR721 preset smart contract from Openzeppelin for studying.
I would like to add a new field when i mint new token to store a string (public).
At the moment there is only the field "to:address" (screenshot below)
I'm sure i need to add something in the mint function:
Easiest way to store the message on blockchain is to emit an event. Event is permanently stored and publicly readable.
Define new MintMessage event outside the mint() function. I don't recommend expanding the default Transfer event that is used during minting, because external tools (such as Etherscan) might ignore the non-standard event and not show minted tokens as a result.
Add a new argument to the mint() function
Emit the MintMessage event within the mint() function
event MintMessage(string message);
function mint(address to, string message) public virtual {
// keep the rest of your function as is
// add a new line emiting the event to the end of the function
emit MintMessage(message);
}

IERC20 public declaration with another address?

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.