- Dependencies
- Installation
- Additional Packages
- Folder & File Structure
- Draft Contract
- Version Control
- Post Contract & Test Development Steps
- Contract List
- Contracts
- Utility Contracts
- Contract Interfaces
IERC721BurnableIERC721MinableIERC721MinterBurnableIRandomNumberGenerator
OpenZeppelin Version: ^4.3.3
Solidity Version: ^0.8.0
Clone the repository as submodule and place it in the ~/contracts/library directory
⚠️ Always remove the artifacts and cache directory when use it as a submodule⚠️
- python3 & pip3
brew install python3- solc-select
pip3 install solc-selectTo install slither
pip3 install slither-analyzerInstall the version of solidity compiler
solc-select install {version}
e.g.
solc-select install 0.8.4Implement the wanted version
solc-select use {version}
e.g.
solc-select use 0.8.4Run static analysis with slither
yarn run slither.
├── contracts # Contracts folder
│ ├── interfaces # Interface contracts
│ ├── mocks # Mock contracts for testing
│ ├── utils # Utility contracts
│ └── ...
├── test # Test scripts folder
│ ├── helper.js # Test helper functions for testing
│ └── ... # Test files with *.test.js
└── ...
For any unfinished contract, please name it with the prefix draft-.
e.g.
draft-Contract.sol
The prefix draft- should be deleted only after test cases were completed with 100% coverage and confirmed it is bug-free.
Please be aware that new version of a contract should be created if any change is wanted to be made to a deployed contract with Vn while n is the version number
e.g.
Payable.sol to PayableV2.sol as Payable.sol has been deployed in other project
New version of PayableV2.sol will be PayableV3.sol, PayableV4.sol, PayableV5.sol, ...
npx hardhat coverage
# with harthat-shorthand installed
hh coverageyarn run slitherIERC721BurnableIERC721MinableIERC721MinterBurnableIRandomNumberGenerator
Contract
Vesting contract that supports single ERC20 that linearly distributes tokens over time. Each address can contain its own vesting schedule including the start time, duration, cliff duration and amount of tokens.
- Deploy the contract with the vesting token address
- Transfer sufficient amount of vesting token to the contract
- Use
addVestingto add a vesting wallet to the contract
Contract
Random number generator contract that implements the Chainlink Oracle Service's Verifiable Random Function
- Create a subscription to Chainlink VRF in the target chain
- Fund the subscription with $LINK
- Get the
vrfCoordinatoraddress andkeyHashof the target chain in Chainlink docs - Deploy the contract with the following parameters:
subcriptionId: the subscription ID of the target chain created at Chainlink VRFvrfCoordinator: the address of the VRF coordinatorkeyHash: the key hash of the target chain
- Copy the deployed
VRFRandomNumberGeneratoraddress and add it as a consumer in the created subscription in Chainlink VRF - Run
requestRandomWordsfunction to fill up the first queue - Always make sure the subscription is funded with $LINK
Utility Contract
Utility contract that provides functions for payment control for both native tokens and ERC20 tokens with 1 fee receiver
Extends with
import "./library/contracts/utils/Payable.sol";
contract Contract is Payable {
constructor (
address payable _feeReceiver
)
Payable(_feeReceiver)
{
// ...
}
}Switch between native token and ERC20 token
// Run following functions with owner account
const erc20 = await ethers.getContract('Erc20')
await contract.setIsErc20(erc20.address)
await contract.setIsNonErc20()Payment
// Run following function in contract
function fn(uint256 _amount) public payable {
pay(_amount);
// ...
}Utility Contract
Utility contract that provides functions for staking period control, including staking period start, end and reward end time in both block.timestamp and block.number measures
Extends with
import "./library/contracts/utils/StakingPeriodControl.sol";
contract Contract is StakingPeriodControl {
# instead of setting up with constructor, additional initailize() function should be used
function initialize(
uint256 _isTimestamp,
uint256 _start,
uint256 _end,
uint256 _bonusEnd
) {
__StakingPeriodControl__init(_isTimestamp, _start, _end, _bonusEnd);
}
}Provided modifiers
beforeStakeStartafterStakeStartbeforeStakeEndafterStakeEndbeforeBonusEndafterBonusEnd
Utility Contract
Utility contract that provides functions for whitelist control with merkle tree implementation
Extends with
import "./library/contracts/utils/Whitelist.sol";
contract Contract is Whitelist {
// ...
}Provided modifier
onlyWhitelisted(bytes32[] memory proof)
// Contract level implementation
function fn(bytes32[] memory _proof) public onlyWhitelisted(_proof) {
// ...
}To add whitelist
const keccal256 = require('keccak256')
const { MerkleTree } = require('merkletreejs')
const addresses = [...]
const tree = new MerkleTree(addresses, keccak256, { hashLeaves: true, sortPairs: true })
await contract.addTree(tree.getRoot())
// save hashed addresses for later use
const hashedAddresses = addresses.map(address => keccal256(address))
// ...To run function with whitelist
const keccal256 = require('keccak256')
const { MerkleTree } = require('merkletreejs')
const targetAddress = '0x...'
// this should be generated when adding the address to the whitelist
const hashedAddresses = []
const tree = new MerkleTree(hashedAddresses, keccal256, { hashLeaves: false, sortPairs: true })
const leaf = keccal256(targetAddress)
const proof = tree.getProof(leaf)
// proof is always needed for whitelist checking, input [] when not needed
await contract.fn(proof)Contract Interface
Interface ERC721 with burn function supported
IERC721IERC721MetadataIERC721Enumerable
burn(uint256 tokenId)