编译器
0.8.26+commit.8a97fa7a
文件 1 的 6:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 2 的 6:ECDSA.sol
pragma solidity ^0.8.20;
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
error ECDSAInvalidSignature();
error ECDSAInvalidSignatureLength(uint256 length);
error ECDSAInvalidSignatureS(bytes32 s);
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError, bytes32) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}
文件 3 的 6:HelloClankerViralGiftFactory.sol
pragma solidity 0.8.26;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
interface IClankerToken {
function name() external returns (string memory);
function symbol() external returns (string memory);
function fid() external returns (uint256);
function deployer() external returns (address);
function image() external returns (string memory);
function castHash() external returns (string memory);
}
interface IERC20Mintable {
function mint(address to, uint256 amount) external;
}
contract HelloClankerViralGiftFactory is Ownable, Pausable {
uint256 public constant BASE_DECIMAL = 1e18;
address private verifyAccount;
address public feeTo;
IERC20Mintable public hcToken;
uint256 public referralRatio = 0.1 * 1e18;
uint256 public feeRatio = 0.01 * 1e18;
uint256 public createIncentive = 50000 * 1e18;
uint256 public claimIncentive = 20000 * 1e18;
uint256 public referralIncentive = 20000 * 1e18;
uint256 public referralForCreatorIncentive = 10000 * 1e18;
struct ViralGiftInfo {
IERC20 token;
uint256 totalAmount;
uint256 remainAmount;
uint256 perClaimAmount;
uint256 perReferralRewards;
uint256 starttime;
uint256 fid;
address account;
mapping(uint256 => address) claimFids;
}
uint256 public expiration_time = 30 days;
uint256 public globalIndex;
mapping(uint256 => ViralGiftInfo) public viralGifts;
event NewViralGift(
uint256 index,
IERC20 _token,
uint256 _totalAmount,
uint256 _perClaimAmount,
uint256 _perReferralRewards,
uint256 _fid,
address _account,
string _memo,
uint256 incentive
);
event Claim(
uint256 index,
IERC20 _token,
uint256 _claimAmount,
uint256 _fid,
address _account,
uint256 _referralFid,
uint256 _referralRewards,
uint256 _claimIncentive,
uint256 _referralIncentive,
uint256 _referralForCreatorIncentive
);
event GetBack(
uint256 index,
IERC20 _token,
uint256 _claimAmount,
uint256 _fid,
address _account
);
event NewReferralRatio(uint256 _oldRatio, uint256 _newRatio);
event NewVerifyAccount(address _oldAddr, address _newAddr);
event NewFee(address _feeTo, uint256 _feeRatio);
event NewIncentive(uint256 _createIncentive, uint256 _claimIncentive, uint256 _referralIncentive);
modifier onlyEOA() {
require(
tx.origin == msg.sender,
"HelloClankerViralGiftFactory: Only EOA."
);
_;
}
modifier onlyFromFrame(uint256 _fid, bytes memory _sig) {
require(
_verifyRequest(_fid, _sig),
"HelloClankerViralGiftFactory: Not From Frame."
);
_;
}
constructor() Ownable(msg.sender) {}
function setReferralRatio(uint256 _referralRatio) external onlyOwner {
uint256 oldReferralRatio = referralRatio;
referralRatio = _referralRatio;
emit NewReferralRatio(oldReferralRatio, _referralRatio);
}
function setVerifyAccount(address _verifyAccount) external onlyOwner {
address oldVerifyAccount = verifyAccount;
verifyAccount = _verifyAccount;
emit NewVerifyAccount(oldVerifyAccount, _verifyAccount);
}
function setFee(address _feeTo, uint256 _feeRatio) external onlyOwner {
feeTo = _feeTo;
feeRatio = _feeRatio;
emit NewFee(_feeTo, _feeRatio);
}
function setHCToken(IERC20Mintable _hcToken) external onlyOwner {
hcToken = _hcToken;
}
function setNewIncentive(uint256 _createIncentive, uint256 _claimIncentive, uint256 _referralIncentive) external onlyOwner {
createIncentive = _createIncentive;
claimIncentive = _claimIncentive;
referralIncentive = _referralIncentive;
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function createViralGift(
IERC20 _token,
uint256 _totalAmount,
uint256 _perClaimAmount,
uint256 _fid,
string memory _memo,
bytes memory _sig
) external onlyEOA onlyFromFrame(_fid, _sig) whenNotPaused {
require(_fid > 0, "Invalid fid.");
ViralGiftInfo storage targetViralGift = viralGifts[globalIndex];
_token.transferFrom(msg.sender, address(this), _totalAmount);
targetViralGift.token = _token;
targetViralGift.totalAmount = _totalAmount;
targetViralGift.remainAmount = _totalAmount;
targetViralGift.perClaimAmount = _perClaimAmount;
targetViralGift.perReferralRewards = _perClaimAmount * referralRatio / BASE_DECIMAL;
targetViralGift.starttime = block.timestamp;
targetViralGift.fid = _fid;
targetViralGift.account = msg.sender;
hcToken.mint(msg.sender, createIncentive);
emit NewViralGift(
globalIndex,
_token,
_totalAmount,
_perClaimAmount,
targetViralGift.perReferralRewards,
_fid,
msg.sender,
_memo,
createIncentive
);
globalIndex++;
}
function claimGift(
uint256 _fid,
uint256 _referralFid,
uint256 _targetIndex,
bytes memory _sig
) external onlyEOA onlyFromFrame(_fid, _sig) whenNotPaused {
ViralGiftInfo storage targetViralGift = viralGifts[_targetIndex];
require(targetViralGift.fid > 0, "Not exist viral gift.");
require(targetViralGift.fid != _fid, "Not allow creater claim the gift.");
require(_fid > 0, "Invaild fid.");
require(targetViralGift.claimFids[_fid] == address(0), "Already Claimed.");
require(_referralFid == 0 || targetViralGift.claimFids[_referralFid] != address(0), "Invaild referral fid.");
require(
targetViralGift.starttime + expiration_time > block.timestamp,
"Expiration."
);
if (_referralFid > 0) {
require(targetViralGift.remainAmount >= targetViralGift.perClaimAmount + targetViralGift.perReferralRewards, "Not enough balance.");
targetViralGift.token.transfer(targetViralGift.claimFids[_referralFid], targetViralGift.perReferralRewards);
targetViralGift.remainAmount -= targetViralGift.perReferralRewards;
hcToken.mint(targetViralGift.claimFids[_referralFid], referralIncentive);
} else {
require(targetViralGift.remainAmount >= targetViralGift.perClaimAmount, "Not enough balance.");
}
targetViralGift.token.transfer(msg.sender, targetViralGift.perClaimAmount);
targetViralGift.remainAmount -= targetViralGift.perClaimAmount;
targetViralGift.claimFids[_fid] = msg.sender;
hcToken.mint(msg.sender, claimIncentive);
hcToken.mint(targetViralGift.account, referralForCreatorIncentive);
emit Claim(
_targetIndex,
targetViralGift.token,
targetViralGift.perClaimAmount,
_fid,
msg.sender,
_referralFid,
targetViralGift.perReferralRewards,
claimIncentive,
referralIncentive,
referralForCreatorIncentive
);
}
function getBackExpiratedRedPackage(uint256 _targetIndex) external onlyEOA whenNotPaused {
ViralGiftInfo storage targetViralGift = viralGifts[_targetIndex];
require(targetViralGift.account == msg.sender, "Not viral gift sender.");
require(targetViralGift.remainAmount > 0, "Zero remain amount.");
require(targetViralGift.starttime + expiration_time >= block.timestamp, "Not Expiration.");
uint256 claimedAmount = targetViralGift.remainAmount;
targetViralGift.token.transfer(msg.sender, claimedAmount);
targetViralGift.remainAmount = 0;
emit GetBack(_targetIndex, targetViralGift.token, claimedAmount, targetViralGift.fid, msg.sender);
}
function _verifyRequest(
uint256 _fid,
bytes memory _sig
) internal view returns (bool) {
bytes32 messageHash = keccak256(abi.encode(_fid, msg.sender));
bytes32 requestHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash));
(address sigAddress, ,) = ECDSA.tryRecover(requestHash, _sig);
return sigAddress == verifyAccount;
}
}
文件 4 的 6:IERC20.sol
pragma solidity ^0.8.20;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 5 的 6:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 6 的 6:Pausable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Pausable is Context {
bool private _paused;
event Paused(address account);
event Unpaused(address account);
error EnforcedPause();
error ExpectedPause();
constructor() {
_paused = false;
}
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
{
"compilationTarget": {
"contracts/HelloClankerViralGiftFactory.sol": "HelloClankerViralGiftFactory"
},
"evmVersion": "berlin",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 100000
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"contract IERC20","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_claimAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fid","type":"uint256"},{"indexed":false,"internalType":"address","name":"_account","type":"address"},{"indexed":false,"internalType":"uint256","name":"_referralFid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_referralRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_claimIncentive","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_referralIncentive","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_referralForCreatorIncentive","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"contract IERC20","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_claimAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fid","type":"uint256"},{"indexed":false,"internalType":"address","name":"_account","type":"address"}],"name":"GetBack","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_feeTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"_feeRatio","type":"uint256"}],"name":"NewFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_createIncentive","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_claimIncentive","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_referralIncentive","type":"uint256"}],"name":"NewIncentive","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newRatio","type":"uint256"}],"name":"NewReferralRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldAddr","type":"address"},{"indexed":false,"internalType":"address","name":"_newAddr","type":"address"}],"name":"NewVerifyAccount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"contract IERC20","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_totalAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_perClaimAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_perReferralRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fid","type":"uint256"},{"indexed":false,"internalType":"address","name":"_account","type":"address"},{"indexed":false,"internalType":"string","name":"_memo","type":"string"},{"indexed":false,"internalType":"uint256","name":"incentive","type":"uint256"}],"name":"NewViralGift","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"BASE_DECIMAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fid","type":"uint256"},{"internalType":"uint256","name":"_referralFid","type":"uint256"},{"internalType":"uint256","name":"_targetIndex","type":"uint256"},{"internalType":"bytes","name":"_sig","type":"bytes"}],"name":"claimGift","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_totalAmount","type":"uint256"},{"internalType":"uint256","name":"_perClaimAmount","type":"uint256"},{"internalType":"uint256","name":"_fid","type":"uint256"},{"internalType":"string","name":"_memo","type":"string"},{"internalType":"bytes","name":"_sig","type":"bytes"}],"name":"createViralGift","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expiration_time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_targetIndex","type":"uint256"}],"name":"getBackExpiratedRedPackage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"globalIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hcToken","outputs":[{"internalType":"contract IERC20Mintable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralForCreatorIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTo","type":"address"},{"internalType":"uint256","name":"_feeRatio","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Mintable","name":"_hcToken","type":"address"}],"name":"setHCToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_createIncentive","type":"uint256"},{"internalType":"uint256","name":"_claimIncentive","type":"uint256"},{"internalType":"uint256","name":"_referralIncentive","type":"uint256"}],"name":"setNewIncentive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_referralRatio","type":"uint256"}],"name":"setReferralRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_verifyAccount","type":"address"}],"name":"setVerifyAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"viralGifts","outputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"remainAmount","type":"uint256"},{"internalType":"uint256","name":"perClaimAmount","type":"uint256"},{"internalType":"uint256","name":"perReferralRewards","type":"uint256"},{"internalType":"uint256","name":"starttime","type":"uint256"},{"internalType":"uint256","name":"fid","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function"}]