Skip to content

๐Ÿ“ƒ Contract Configuration

Sasha Boginsky edited this page May 8, 2023 · 6 revisions

This wiki provides details on creating and deploying an ERC1155 NFT, as well as configuring RPS, Rock-Paper-Scissors-Mint's contract. It assumes you have configured the Hardhat project already.

Creating a Contract

Head over to the OpenZeppelin Contracts Wizard and fill out the generator for ERC1155. (See RPS Configuration in OpenZeppelin ERC1155 Notes)

Interacting with a Contract

Open the contract in the Remix IDE to interact with it.

Compatibility with OpenSea

When hitting uri you will get a uri in the same format as the output shown below:

Unsupported uri output

OpenSea does not support the returned URI format, so we will need to overwrite the uri function to return it in the correct format.

  1. Import StringsUpgradeable.sol, an OpenZeppelin contract to convert Integer to String.

  2. Override the uri function with a custom one which converts the passed token id from an integer to a string and returns the complete URI.


// contracts/RPS.sol
import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
//...
function uri(uint256 _tokenid) override public pure returns (string memory) {
    return string(
         abi.encodePacked(
             "https://ipfs.io/ipfs/bafybeicxlrrqm5l6uqtngfmdgrzzqrklu2vdqwg3dx32fcqpffh7qyryju/",
             StringsUpgradeable.toString(_tokenid),".json"
         )
     );
 }
  1. Compile and Deploy

  2. Hit uri again and see the difference:

Supported uri output

Configuration

  1. Add your Solidity contract (.sol) to the contracts directory

  2. Create a deploy directory

    mkdir deploy
  3. Add your TypeScript (.ts) deployment script in the deploy directory.

    • RPS contract's deployment script, 001_deploy_rps.ts, annotated for reference
      import { HardhatRuntimeEnvironment } from 'hardhat/types';
      import { DeployFunction } from 'hardhat-deploy/types';
      
      import { LOCAL_NETWORKS } from '../constants'
      
      const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
        /**
         * If this script is run directly using `node`, you may want to call
         * `compile` manually to make sure everything is compiled
        **/
      
        // await hre.run('compile');
      
        const {
          deployments,
          ethers,
          getNamedAccounts,
          upgrades
        } = hre;
        const { getNetworkName } = deployments;
        const { deployProxy, erc1967 } = upgrades;
      
        const targetNetwork = await getNetworkName();
        const { deployer } = await getNamedAccounts();
      
        // ############## DEPLOYING ###############
      
        const RPS = await ethers.getContractFactory('RPS');
      
        console.log(`Deployer ${deployer} is deploying RPS to the ${targetNetwork} network...`);
      
        // `hre.upgrades.deployProxy` will deploy the new implementation contract
        // (unless there is one already from a previous deployment)
        const proxy = await deployProxy(RPS, [], {
          initializer: 'initialize',
          kind: 'transparent',
        });
      
        await proxy.deployed();
      
        console.log('RPS deployed to: ', proxy.address);
      
        const implementationAddr = await erc1967.getImplementationAddress(
          proxy.address
        );
      
        // ############## VERIFICATION ###############
      
        // run verification when the contract is not deployed on a local network (localhost, hardhat)
        if (!LOCAL_NETWORKS.includes(targetNetwork)) {
          console.log('Waiting 60s to verify');
      
          await new Promise<void>((resolve) => {
            setTimeout(async () => {
              await run('verify:verify', {
                address: implementationAddr, // implementation address
              }).catch((e) => console.error(`ERROR: ${e}`));
              resolve();
            }, 60 * 1000);
          });
        }
      };
      
      export default func;
      
      func.tags = ['RPS'];
    • Etherscan Verification

      • The @nomiclabs/hardhat-etherscan package enables us to verify by running the verify task, passing the address of the contract and the constructor arguments that were used to deploy it (if any).
      • Verification throws an error when the contract has already been verified
      • Notice that our verification is pointing to the implementation, not proxy address.