编译器
0.6.12+commit.27d51765
文件 1 的 8:ICommunityRewards.sol
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721.sol";
import "../interfaces/IERC20withDec.sol";
interface ICommunityRewards is IERC721 {
function rewardsToken() external view returns (IERC20withDec);
function claimableRewards(uint256 tokenId) external view returns (uint256 rewards);
function totalVestedAt(
uint256 start,
uint256 end,
uint256 granted,
uint256 cliffLength,
uint256 vestingInterval,
uint256 revokedAt,
uint256 time
) external pure returns (uint256 rewards);
function grant(
address recipient,
uint256 amount,
uint256 vestingLength,
uint256 cliffLength,
uint256 vestingInterval
) external returns (uint256 tokenId);
function loadRewards(uint256 rewards) external;
function revokeGrant(uint256 tokenId) external;
function getReward(uint256 tokenId) external;
event RewardAdded(uint256 reward);
event Granted(
address indexed user,
uint256 indexed tokenId,
uint256 amount,
uint256 vestingLength,
uint256 cliffLength,
uint256 vestingInterval
);
event GrantRevoked(uint256 indexed tokenId, uint256 totalUnvested);
event RewardPaid(address indexed user, uint256 indexed tokenId, uint256 reward);
}
文件 2 的 8:IERC165.sol
pragma solidity ^0.6.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 3 的 8:IERC20.sol
pragma solidity ^0.6.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 4 的 8:IERC20withDec.sol
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol";
interface IERC20withDec is IERC20 {
function decimals() external view returns (uint8);
}
文件 5 的 8:IERC721.sol
pragma solidity ^0.6.2;
import "../../introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}
文件 6 的 8:IMerkleDistributor.sol
pragma solidity 0.6.12;
interface IMerkleDistributor {
function communityRewards() external view returns (address);
function merkleRoot() external view returns (bytes32);
function isGrantAccepted(uint256 index) external view returns (bool);
function acceptGrant(
uint256 index,
uint256 amount,
uint256 vestingLength,
uint256 cliffLength,
uint256 vestingInterval,
bytes32[] calldata merkleProof
) external;
event GrantAccepted(
uint256 indexed tokenId,
uint256 indexed index,
address indexed account,
uint256 amount,
uint256 vestingLength,
uint256 cliffLength,
uint256 vestingInterval
);
}
文件 7 的 8:MerkleDistributor.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/cryptography/MerkleProof.sol";
import "../interfaces/ICommunityRewards.sol";
import "../interfaces/IMerkleDistributor.sol";
contract MerkleDistributor is IMerkleDistributor {
address public immutable override communityRewards;
bytes32 public immutable override merkleRoot;
mapping(uint256 => uint256) private acceptedBitMap;
constructor(address communityRewards_, bytes32 merkleRoot_) public {
require(communityRewards_ != address(0), "Cannot use the null address");
require(merkleRoot_ != 0, "Invalid merkle root provided");
communityRewards = communityRewards_;
merkleRoot = merkleRoot_;
}
function isGrantAccepted(uint256 index) public view override returns (bool) {
uint256 acceptedWordIndex = index / 256;
uint256 acceptedBitIndex = index % 256;
uint256 acceptedWord = acceptedBitMap[acceptedWordIndex];
uint256 mask = (1 << acceptedBitIndex);
return acceptedWord & mask == mask;
}
function _setGrantAccepted(uint256 index) private {
uint256 acceptedWordIndex = index / 256;
uint256 acceptedBitIndex = index % 256;
acceptedBitMap[acceptedWordIndex] = acceptedBitMap[acceptedWordIndex] | (1 << acceptedBitIndex);
}
function acceptGrant(
uint256 index,
uint256 amount,
uint256 vestingLength,
uint256 cliffLength,
uint256 vestingInterval,
bytes32[] calldata merkleProof
) external override {
require(!isGrantAccepted(index), "Grant already accepted");
bytes32 node = keccak256(abi.encodePacked(index, msg.sender, amount, vestingLength, cliffLength, vestingInterval));
require(MerkleProof.verify(merkleProof, merkleRoot, node), "Invalid proof");
_setGrantAccepted(index);
uint256 tokenId = ICommunityRewards(communityRewards).grant(
msg.sender,
amount,
vestingLength,
cliffLength,
vestingInterval
);
emit GrantAccepted(tokenId, index, msg.sender, amount, vestingLength, cliffLength, vestingInterval);
}
}
文件 8 的 8:MerkleProof.sol
pragma solidity >=0.6.0 <0.8.0;
library MerkleProof {
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
return computedHash == root;
}
}
{
"compilationTarget": {
"contracts/rewards/MerkleDistributor.sol": "MerkleDistributor"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 100
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"communityRewards_","type":"address"},{"internalType":"bytes32","name":"merkleRoot_","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vestingLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cliffLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vestingInterval","type":"uint256"}],"name":"GrantAccepted","type":"event"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"vestingLength","type":"uint256"},{"internalType":"uint256","name":"cliffLength","type":"uint256"},{"internalType":"uint256","name":"vestingInterval","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"acceptGrant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"communityRewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"isGrantAccepted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]