Solidity 0.5.1, when creating a contract object, why do we have to pass the token to that contract's constructor even if there is no constructor - constructor

Here is the code:
pragma solidity 0.5.1;
contract ERC20Token{
string public name;
mapping(address => uint256) public balances;
function mint() public{
balances[tx.origin] += 1;
}
}
contract MyContract {
address payable wallet;
address public token;
constructor(address payable _wallet, address _token) public {
wallet = _wallet;
token = _token;
}
function() external payable {
buyToken();
}
function buyToken() public payable{
ERC20Token _token = ERC20Token(address(token));
_token.mint();
wallet.transfer(msg.value);
}
}
Process:
First, we are getting the ERC20Token contract address by deploying the ERC20Token contract in the first place.
Secondly, MyContract constructor takes (a wallet address and the ERC20Token contract address) as two parameters.
Then, we create a ERC20Token contract object from this line
ERC20Token _token = ERC20Token(address(token));
I got confused by how this line worked. Even the ERC20Token contract does not contain any constructor, where the above code passes the token as a parameter to the ERC20Token constructor.
If i delete the token parameter from the above code:
ERC20Token _token = ERC20Token();
I will get an error called
Exactly one argument expected for explicit type conversion
Could anyone explain to me why this happens in solidity?

Without the new keyword, you're making a pointer to an already deployed instance of the ERC20Token contract, passing its address in the argument. Since the contract is already deployed and the constructor has been already executed, you do not pass its constructor params.
// address of existing instance
ERC20Token _token = ERC20Token(address(token));
With the new keyword, you'd be deploying a new instance of ERC20Token, specifying its constructor params. Its address is then available by typecasting the variable to address type.
// creating new instance
// passing constructor params (in your case empty)
ERC20Token _token = new ERC20Token();
// address of the newly deployed contract
address tokenAddress = address(_token);

Related

Setting initial supply for factory contract generated token

I wrote a factory contract for generating some tokens and it is able to successfully create tokens. However, when I import the generated token address to my wallet, the supply is 0 even though I have set it to a value:
Factory contract snippet:
contract TokenFactory {
event MyTokenCreated(address contractAddress);
function createNewMyToken() public returns (address) {
MyToken myToken = new MyToken(2000000);
emit MyTokenCreated(address(myToken));
return address(myToken);
}
MyToken.sol
pragma solidity ^0.8.7;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor (uint256 initialSupply) ERC20("MyToken", "MY") {
_mint(msg.sender, initialSupply * 10 ** 18);
}
}
After generating MyToken from TokenFactory and importing the generated token's address to my wallet, I expected the supply to be 2000000, but it is 0.
Does anyone have any idea why this is happening?
Note that you are sending tokens to msg.sender, and in this case, the msg.sender will always be the factory contract. So if you want to mint those tokens to your own wallet, you can either give MyToken a new address param where your factory contract will pass your address, or just use tx.origin, so that it references the transaction original creator address.

Constructor of factory-like smart contract keeps reverting

I'm working with 2 contracts, one that manages users bets for a specific football match and another (factory style) that generates these individual contracts to be managed separately.
The Generator contract is this:
pragma solidity ^0.8.0;
contract Generator {
address immutable public owner;
string public matchGenerated;
Management[] public bettingHistory;
constructor(string memory _league, string memory _match) {
owner = msg.sender;
matchGenerated = string(abi.encodePacked(_league, "_", _match));
Management newBetContract = new Management(address(this));
bettingHistory.push(newBetContract);
}
}
The Management contract receives data from the Generator to define the manager and the match values, as follows (short version):
contract Management {
address payable immutable public manager;
string public matchDispute;
Generator generator;
constructor(address _contract) {
generator = Generator(_contract);
manager = payable(generator.owner());
matchDispute = generator.matchGenerated();
}
Once I try to deploy the Generator contract in Remix it results in a reverting error. If I remove the instance of the generator in the Management contract and repeat the constructor arguments in both contracts it works, but I want to avoid the redundancy and get the values already stored in the Generator variables automatically.
To implement the above using interface, your solution will be like:
Generator.sol file
pragma solidity ^0.8.0;
contract Generator {
address immutable public owner;
string public matchGenerated;
Management[] public bettingHistory;
constructor(string memory _league, string memory _match) {
owner = msg.sender;
matchGenerated = string(abi.encodePacked(_league, "_", _match));
Management newBetContract = new Management(address(this));
bettingHistory.push(newBetContract);
}
}
IGenerator.sol file
pragma solidity ^0.8.0;
interface IGenerator{
function owner() external view returns (address);
function matchGenerated() external view returns (string)
}
Management.sol file
pragma solidity ^0.8.0;
import "IGenerator.sol";
contract Management {
address payable immutable public manager;
string public matchDispute;
constructor(address _contract) {
manager = payable(IGenerator(_contract).owner());
matchDispute = IGenerator(_contract).matchGenerated();
}
As you can see above, I have exposed all functions of Generator that management needed and separated the definitions of the two. Try that and see if it works and if not let's know what the new error messages are.

What is the use of Uniswap Router Initialization in a Token Contract

I just started on building Tokens using ETH & BSC, this is one statement which I see in many Contracts.
Inside the Constructor method, the Uniswap router is iniliazed probably with the V2 version. What is the use of this?
constructor () public {
_rOwned[_msgSender()] = _rTotal;
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
// Create a uniswap pair for this new token
uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
.createPair(address(this), _uniswapV2Router.WETH());
// set the rest of the contract variables
uniswapV2Router = _uniswapV2Router;
Why is this initialization required? What is the functionality of this?
Appreciate if someone could help.
Thanks
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
This line initializes a pointer to the 0x10ED... address and expects the contract (deployed at the 0x10ED... address) to implement the IUniswapV2Router02 interface.
The interface is defined somewhere with the caller contract source code.
It allows you to execute and call functions defined by the interface instead of building low-level calls. It also allows you to use the returned datatypes instead of parsing the returned binary.
Example:
pragma solidity ^0.8.5;
interface IRemote {
function foo() external view returns (bool);
}
contract MyContract {
IRemote remote;
constructor() {
remote = IRemote(address(0x123));
}
function getFoo() external view returns (bool) {
bool returnedValue = remote.foo();
return returnedValue;
}
}

Getting contract address

I saw an example about this, while was searching it on the internet.
I want to deploy a new contract which is ProjectContract. However, I could not get contract address as below. I think this is for old version.
address newProjectAddress = new ProjectContract(name, description, requiredPrice, msg.sender);
And the error message is:
How can I do that for the new versions?
When you're creating new <contractName>, it returns the contract instance. You can cast it to the address type and get the contract address.
pragma solidity ^0.8.4;
contract ProjectContract {
constructor (string memory name, string memory description, uint256 requiredPrice, address owner) {
}
}
contract MyContract {
event LogAddress(address _address);
function createProjectContract(string memory name, string memory description, uint256 requiredPrice) external {
ProjectContract newProjectInstance = new ProjectContract(name, description, requiredPrice, msg.sender);
address newProjectAddress = address(newProjectInstance); // here
emit LogAddress(newProjectAddress);
}
}

Solidity public variable getter call doesn't return

I have deployed a very basic solidity contract (pragma solidity^0.4.0) to Rinkeby. When I call the getters on my state variables, nothing is returned and I do not understand why. To compile the contract I'm using "solc": "^0.4.25"
Using Remix to test, the call to the getter works locally without issue. However, the call doesn't work on my contract on Rinkeby.
Here is my solidity code...
pragma solidity^0.4.0;
contract Contest {
address public manager;
uint public submissionCost;
uint8 public votesPerSubmission;
constructor (uint _submissionCost, uint8 _votesPerSubmission) public {
manager = msg.sender;
submissionCost = _submissionCost;
votesPerSubmission = _votesPerSubmission;
}
modifier restricted() {
require(msg.sender == manager, "Not authorized.");
_;
}
function adjustSubmissionCost(uint32 newCost) public restricted {
submissionCost = newCost;
}
function adjustVotesPerSubmission(uint8 newVotes) public restricted {
votesPerSubmission = newVotes;
}
}
The address of the deployed contract on Rinkeby is
0xacBd19113e0D8122E18DF48A320b635fB5D7Cdd0
https://rinkeby.etherscan.io/address/0xacbd19113e0d8122e18df48a320b635fb5d7cdd0
When calling any of the public variables from Remix, I expect a return value, however I only receive the message call to Contest.manager in the Remix console and nothing more.
I get the same behavior in my web3 dapp, with zero return when I try...
await Contest.methods.manager().call()