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.
Related
I'm actually trying to create an NFT Marketplace, where a user can upload his NFT (create/mint new NFT) and other users can give some Ether and mint the same NFT. Trying to achieve this with the ERC721 standard. Maybe ERC1155 will be a better choice but I have to use ERC721.
So, I think how I can achieve this using ERC721 by minting NFTs with different tokenIDs but with pointing to the same NFT metadata or TokenURI.
I know this is possible as mentioned in this post: https://ethereum.stackexchange.com/questions/59765/two-erc721-tokens-that-refer-to-the-same-metadata
But I can't fo it programatically.
This is how I'm trying: (It's not working, even 1 NFT is not showing on he opensea testnet)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import "#openzeppelin/contracts/utils/Strings.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract navich is ERC721URIStorage, Ownable {
using Strings for uint256;
using Counters for Counters.Counter;
Counters.Counter private _tokenId;
string public baseURI = "ipfs://QmRyezUtChrpvH4i4wKEoPngwTFKHuu4YYjZrSg89wvqVq/";
constructor() ERC721("Wagmi", "Wagmi") {}
function mintNFT() public payable {
uint256 dynamic = 1;
_tokenId.increment();
_mint(msg.sender, _tokenId.current());
_setTokenURI(dynamic, baseURI);
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
return
string(
abi.encodePacked(
baseURI,
tokenId.toString(),
".json"
)
);
}
// function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
// require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
// return "ipfs://QmRyezUtChrpvH4i4wKEoPngwTFKHuu4YYjZrSg89wvqVq";
// }
}
Incidentally, this is not the full Marketplace code.
code
trying to create contract using KIP37 as base contract. its works fine for the previous version of #klaytn/contracts - 0.9.0, but it is not working for #klaytn/contracts - 1.0.0
//SPDX-License-Identifier: Unlincesed
pragma solidity ^0.8.0;
import "#klaytn/contracts/contracts/KIP/token/KIP37/KIP37.sol";
// this line showing error "Contract ItemMint should be abstract
contract ItemMint is KIP37 {
string public name;
constructor(string memory _name) {
name = _name;
}
function mint(address to) public pure returns (bool) {
require(msg.sender == to , "your are authorized");
return true;
}
}
using npm i #klaytn/contracts - 1.0.0
The parent KIP37 contract defines a constructor that takes one argument - a string named uri_, so you need to invoke the parent constructor as well.
constructor(string memory _name, string memory uri_) KIP37(uri_) {
name = _name;
}
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);
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;
}
}
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()