There are two ways of declaration ERC20 in other contracts:
IERC20 public token, and then connecting to it like token.transfer;
address public token, and then connecting to it like IERC20(token).transfer.
Is there any difference between these two ways of declaration? If so, what is more preferred for usage?
The only difference is during compilation, when the compiler would give you an error if you tried to use one type where the other is required.
In terms of runtime, they are both (160-bit) ethereum addresses.
In your example, it makes more sense to use the type IERC20, because that is the intended type of the variable token.
Related
I am a beginner and I want to test private functions.
Is there a possibility on remix?
Thanks for any hint and support.
No, there is no way to test private methods, unless you create a getter for said method.
Private variables and methods have restricted (write) access to the current instance of the contract. Can't be accessed by inherited contracts, proxy or externally called.
I have a ERC-721 smart contract defined like this
contract MintNFT is ERC721Enumerable, Ownable {
constructor(string _name, string _symbol) ERC721(_name, _symbol){}
}
in which I mint the NFTs and few more functions. Then I have created a new contract to purchase the NFTs and manage some stuff, but it forces me to mark it as abstract no matter what I write in the contract. I defined it like this:
contract ManagerNFT is MintNFT, IERC721 {
constructor(string memory _name, string memory _symbol) MintNFT(_name, _symbol){}
}
It throws an error saying linearization of inheritance graph impossible it goes away when I mark this ManagerNFT contract to abstract.
I don't know why this happens, I'm setting the constructors correctly I think, any thoughts on how to do this? Thanks.
As the IERC721 name suggests, it's an interface.
So the ManagerNFT needs to implement all functions of the interface.
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.
I am trying to make a contract that has two different tokens used for different aspects of the contract. I would like both of the tokens to be able to fit ERC20 standards but I am not sure how to specify unique variables and functions for each.
If you consider the structure of an ERC 20 token : https://github.com/ConsenSys/Tokens/blob/master/Token_Contracts/contracts/Token.sol , you will see that what you are proposing, although possible, would be a little messy. But more importantly it would transform your token contract into a non-ERC20 token.
uint256 public totalSupply; would need to be replaced with either a mapping or a two separate parameters.
The same would be for managing balances, you would need to change the signature of each method to take an additional parameter for specifying the token you want or create specific method for each token within the contract:
function balanceOf(address _owner) constant returns (uint256 balance);
Would need to be either:
function balanceOf(address _owner, uint256 token_id) constant returns (uint256 balance);
or
function balanceOfTokenA(address _owner) constant returns (uint256 balance);
function balanceOfTokenB(address _owner) constant returns (uint256 balance);
But like I said, either implementation would make your token contract a non-ERC20 token.
You would be better off having two contracts, then both would be ERC20 compatible. You could then write a third contract for managing them if your requirements are that they need to be interfaced via a single contract.
These days, ERC1155, a "multi-token" standard, seems like a good choice for contracts needing multiple tokens:
https://github.com/ethereum/EIPs/issues/1155
Simple Summary:
A standard interface for contracts that manage multiple token types. A
single deployed contract may include any combination of fungible
tokens, non-fungible tokens or other configurations (e.g.
semi-fungible tokens).
See also the openzeppelin implementation
As a trained programmer, I have been taught, repeatedly to use getter and setter methods to control the access and modification of class variables. This is how you're told to do it in Java, Python, C++ and pretty much every other modern language under the sun. However, when I started learning about web development, this seemed cast aside. Instead, we're told to use one URL with GET and POST calls, which seems really odd.
So imagine I have a Person object and I want to update their age. In the non-HTTP world, you're supposed to have a method called <PersonObject>.getAge() and another method called <PersonObject>.setAge(int newAge). But say, instead, you've got a webserver that holds user profile information. According to HTTP conventions, you'd have a URL like '/account/age'. To get their age, you'd request that URL with a 'GET', and to set their age, you'd request that URL with a 'POST' and somehow (form, JSON, URL-arg, etc.) send the new value along.
The HTTP method just feels awkward. To me, that's analogous to changing the non-HTTP version to one method called age, and you'd get their age with <PersonObject>.age('GET'), and set their age with <PersonObject>.age(newAge, 'SET'). Why is it done that way?
Why not have one URL called '/account/getAge' and another called '/account/setAge'?
What you are refering to is a RESTful API. While not required (you could just use getters and setters) it is indeed considered good practice. This however does not meen you have to change the code of your data objects. I always use getters and setters for my business logic in the models layer.
What you are talking to through the HTTP request are the controllers however, and they rarely use getters and setters (I suppose I do not need to explain the MVC design pattern to an experienced programmer). You should never directly access your models through HTTP (how about authentication and error handling and stuff...)
If you have some spare time I would advise you to have a look at this screencast, which I found very useful.
You certainly could have separate URLs if you like, but getters and setters can share names in the original context of your question anyway because of overloading.
class Person {
private age;
public age() {
return this.age;
}
public age(int age) {
this.age = age;
}
}
So if it helps you, you can think of it like that.