¡El código fuente de este contrato está verificado!
Metadatos del Contrato
Compilador
0.8.28+commit.7893614a
Idioma
Solidity
Código Fuente del Contrato
Archivo 1 de 7: IERC20.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)pragmasolidity ^0.8.20;/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/interfaceIERC20{
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransfer(address to, uint256 value) externalreturns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/functionallowance(address owner, address spender) externalviewreturns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/functionapprove(address spender, uint256 value) externalreturns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom, address to, uint256 value) externalreturns (bool);
}
Código Fuente del Contrato
Archivo 2 de 7: IPermissionsManager.sol
// SPDX-License-Identifier: None// Super Champs Foundation 2024pragmasolidity ^0.8.24;/// @title Interface for protocol permissions registry/// @author Chance Santana-Wees (Coelacanth/Coel.eth)interfaceIPermissionsManager{
///@notice All available roles.///@dev EXT roles are available for future application.enumRole {
ANY,
GLOBAL_ADMIN,
MINT_ADMIN,
TRANSFER_ADMIN,
SYSTEMS_ADMIN,
EXT1,
EXT2,
EXT3,
EXT4,
EXT5,
EXT6,
EXT7,
EXT8,
EXT9,
EXT10
}
/**
* @param role_ ISCPermissionsManager.Role to query
* @param account_ Address to check for role_
*/functionhasRole(Role role_, address account_) externalviewreturns(bool);
/**
* @param role_ ISCPermissionsManager.Role to add
* @param account_ Address to add role_ on
*/functionaddRole(Role role_, address account_) external;
/**
* @param role_ ISCPermissionsManager.Role to remove
* @param account_ Address to remove role_ from
*/functionremoveRole(Role role_, address account_) external;
}
Código Fuente del Contrato
Archivo 3 de 7: ISCAccessPass.sol
// SPDX-License-Identifier: None// Super Champs Foundation 2024pragmasolidity ^0.8.24;/// @title Interface for protocol metagame metadata registry/// @author Chance Santana-Wees (Coelacanth/Coel.eth)interfaceISCAccessPass{
/// @notice Queries if a specfied address has minted an SBT./// @param addr_ The address to query./// @return _result bool Returns true if the address has minted an SBT .functionisPassHolder(address addr_) externalviewreturns (bool);
/// @notice Queries if a specfied address has been verified./// @param addr_ The address to query./// @return _result bool Returns true if the address has had its verification status set to true.functionisVerified(address addr_) externalviewreturns (bool);
/// @notice Queries level of a specfied address's pass./// @param addr_ The address to query./// @return _result uint256 Returns the level of the user's access pass.functiongetLevel(address addr_) externalviewreturns (uint256);
/// @notice Queries level of a specfied pass./// @param id_ The pass to query./// @return _result uint256 Returns the level of the access pass.functiongetLevel(uint256 id_) externalviewreturns (uint256);
}
// SPDX-License-Identifier: None// Super Champs Foundation 2024pragmasolidity ^0.8.24;import"../../interfaces/IPermissionsManager.sol";
contractSCPermissionedAccess{
IPermissionsManager publicimmutable permissions;
/// @notice Function modifier which requires the sender to possess the global admin permission as recorded in "permissions"modifierisGlobalAdmin() {
require(permissions.hasRole(IPermissionsManager.Role.GLOBAL_ADMIN, msg.sender), "Not a Global Admin");
_;
}
/// @notice Function modifier which requires the sender to possess the systems admin permission as recorded in "permissions"modifierisSystemsAdmin() {
require(permissions.hasRole(IPermissionsManager.Role.SYSTEMS_ADMIN, msg.sender), "Not a Systems Admin");
_;
}
constructor(address _permissions){
permissions = IPermissionsManager(_permissions);
}
}
Código Fuente del Contrato
Archivo 7 de 7: SCSeasonRewards.sol
// SPDX-License-Identifier: None// Super Champs Foundation 2024pragmasolidity ^0.8.24;import"@openzeppelin/contracts/token/ERC20/IERC20.sol";
import"../Utils/SCPermissionedAccess.sol";
import"../../interfaces/IPermissionsManager.sol";
import"../../interfaces/ISCSeasonRewards.sol";
import"../../interfaces/ISCAccessPass.sol";
import"../../interfaces/ISCMetagamePool.sol";
/// @title Manager for the seasonal player rewards program./// @author Chance Santana-Wees (Coelacanth/Coel.eth)/// @dev Season rewards pulled from a treasury contract that must have a token allowance set for this contract./// @notice Allows System Admins to set up and report scores for Seasons.contractSCSeasonRewardsisISCSeasonRewards, SCPermissionedAccess{
///@notice The address of the rewards token. (The CHAMP token)
IERC20 immutable token;
///@notice The traeasury from which Seasons pull their reward tokens.address treasury;
/// @notice The access pass SBT
ISCAccessPass public access_pass;
/// @notice The metagame staking pool
ISCMetagamePool public staking_pool;
///@notice A list of seasons. A season's ID is its index in the list.
ISCSeasonRewards.Season[] public seasons;
///@notice A mapping of scores reported for each user by address for each season by ID.mapping(uint256=>mapping(address=>uint256)) public season_rewards;
///@notice A mapping of quantity of tokens claimed for each user by address for each season by ID.mapping(uint256=>mapping(address=>uint256)) public claimed_rewards;
///@notice A set of signatures which have already been used.///@dev Member signatures are no longer valid.mapping(bytes=>bool) private consumed_signatures;
///@notice A mapping of the last used signature timestamp, by user address.///@dev This acts as the nonce for the signatures. Signatures with timestamps earlier than the value set are not valid.mapping(address=>uint256) public player_last_signature_timestamp;
eventTreasurySet(address treasury);
eventStakedRewards(address staker, uint256 rewards);
///@param permissions_ The address of the protocol permissions registry. Must conform to IPermissionsManager.///@param token_ The address of the reward token. (The CHAMP token)///@param treasury_ The address of the account/contract that the Seasons reward system pulls reward tokens from./// @param access_pass_ Address of the protocol access pass SBTconstructor(address permissions_,
address token_,
address treasury_,
address access_pass_,
address staking_pool_)
SCPermissionedAccess(permissions_)
{
token = IERC20(token_);
treasury = treasury_;
access_pass = ISCAccessPass(access_pass_);
staking_pool = ISCMetagamePool(staking_pool_);
}
///@notice Updates the address of the account/contract that the Seasons reward system pulls reward tokens from.///@dev Only callable by Global Admins.///@param treasury_ The address of the new treasury.functionsetTreasury(address treasury_) externalisGlobalAdmin{
treasury = treasury_;
emit TreasurySet(treasury_);
}
///@notice Initializes a new Season of the rewards program.///@dev Only callable by Systems Admins. It is permissable to create Seasons with overlapping times.///@param start_time_ The start time of the new season.///@return season_ ISCSeasonRewards.Season The Season struct that was initialized.functionstartSeason(uint256 start_time_
) externalisSystemsAdminreturns(ISCSeasonRewards.Season memory season_)
{
require(start_time_ >0, "CANNOT START AT 0");
season_.start_time = start_time_;
season_.end_time =type(uint256).max;
season_.id =uint32(seasons.length);
seasons.push(season_);
}
///@notice Queries the active status of a season.///@param season_ The season struct to query from.///@param timestamp_ The timestamp to query the active status at.///@return _active bool The active status of the provided seasonfunctionisSeasonActive(
Season memory season_,
uint256 timestamp_
) publicpurereturns(bool _active)
{
_active = season_.end_time >= timestamp_ && timestamp_ > season_.start_time;
}
///@notice Queries the finalized status of a season.///@dev A season is finalized if its claim time is set.///@param season_ The season struct to query from.///@return _finalized bool The finalized status of the provided season.functionisSeasonFinalized(
Season memory season_
) publicpurereturns(bool _finalized)
{
_finalized = season_.claim_end_time >0;
}
///@notice Queries if a season has ended.///@param season_ The season struct to query from.///@param timestamp_ The timestamp to query the ended status at.///@return _ended bool True if the season has ended at the provided timestampfunctionisSeasonEnded(
Season memory season_,
uint256 timestamp_
) publicpurereturns(bool _ended)
{
_ended = season_.end_time < timestamp_;
}
///@notice Queries if a season has been finalized and can have rewards claimed from it.///@param season_ The season struct to query from.///@param timestamp_ The timestamp to query the ended status at.///@return _active bool True if the season has ended at the provided timestampfunctionisSeasonClaimingActive(
Season memory season_,
uint256 timestamp_
) publicpurereturns(bool _active)
{
_active = isSeasonFinalized(season_) && season_.claim_end_time >= timestamp_;
}
///@notice Queries if a season has been finalized and the claim period has already elapsed.///@param season_ The season struct to query from.///@param timestamp_ The timestamp to query the ended status at.///@return _ended bool True if the season's rewards claim period has elapsed.functionisSeasonClaimingEnded(
Season memory season_,
uint256 timestamp_
) publicpurereturns(bool _ended)
{
_ended = isSeasonFinalized(season_) && season_.claim_end_time < timestamp_;
}
///@notice Ends a season.///@dev Callable only by Systems Admins.///@param id_ The id of the season to end.functionendSeason(uint256 id_
) externalisSystemsAdmin{
Season storage _season = seasons[id_];
require(_season.start_time >0, "SEASON NOT FOUND");
require(isSeasonActive(_season, block.timestamp), "SEASON NOT ACTIVE");
_season.end_time =block.timestamp;
}
///@notice Revokes unclaimed reward tokens into the treasury.///@dev Callable only by Systems Admins and only after the season's claim period has elapsed.///@param id_ The id of the season to end.functionrevokeUnclaimedReward(uint256 id_
) externalisSystemsAdmin{
Season storage _season = seasons[id_];
uint256 _remaining_reward_amount = _season.remaining_reward_amount;
require(_season.start_time >0, "SEASON NOT FOUND");
require(isSeasonClaimingEnded(_season, block.timestamp), "SEASON_CLAIM_NOT_ENDED");
require(_remaining_reward_amount >0, "ZERO_REMAINING_AMOUNT");
bool transfer_success = token.transfer(treasury, _remaining_reward_amount);
require(transfer_success, "FAILED TRANSFER");
_season.remaining_reward_amount -=uint128(_remaining_reward_amount);
}
///@notice Finalizes a season, setting its rewards quantity and claim period.///@dev Callable only by Systems Admins and only after the season has been ended by calling the endSeason(...) function.///@param id_ The id of the season to finalize.///@param reward_amount_ The quantity of reward tokens to split between season participants. This quantity must be able to be transferred from the treasury.///@param claim_duration_ The duration of the claim period.functionfinalize(uint256 id_,
uint256 reward_amount_,
uint256 claim_duration_
) externalisSystemsAdmin{
Season storage _season = seasons[id_];
require(_season.start_time >0, "SEASON NOT FOUND");
require(isSeasonEnded(_season, block.timestamp), "SEASON_NOT_ENDED");
require(!isSeasonFinalized(_season), "SEASON_FINALIZED");
require(reward_amount_ == _season.reward_amount, "REWARD AMOUNT DOESN'T MATCH");
require(claim_duration_ >=7days&& claim_duration_ <1000days, "CLAIM DURATION OUT OF BOUNDS");
bool transfer_success = token.transferFrom(treasury, address(this), reward_amount_);
require(transfer_success, "FAILED TRANSFER");
_season.remaining_reward_amount = reward_amount_;
_season.claim_end_time =block.timestamp+ claim_duration_;
}
///@notice Reports an list of players' scores for the specified season.///@dev Callable only by Systems Admins.///@param season_id_ The ID of the season.///@param players_ The list of player addresses.///@param rewards_ The list of player's total current rewards.functionreportRewards(uint256 season_id_,
address[] calldata players_,
uint256[] calldata rewards_
) externalisSystemsAdmin{
require(players_.length== rewards_.length, "ARRAYS MISMATCH");
Season storage _season = seasons[season_id_];
require(_season.start_time >0, "SEASON NOT FOUND");
require(!isSeasonFinalized(_season), "SEASON FINALIZED");
uint256 _increase =0;
uint256 _decrease =0;
for (uint256 i =0; i < players_.length; i++) {
_increase += rewards_[i];
_decrease += season_rewards[season_id_][players_[i]];
season_rewards[season_id_][players_[i]] = rewards_[i];
}
_season.reward_amount += _increase;
_season.reward_amount -= _decrease;
}
///@notice Claim tokens rewarded to msg.sender in the specified season. Must have a verified Access Pass.///@dev Callable only on seasons which have been finalized and whose claim duration has not elapsed.///@param season_id_ The season to claim reward tokens from.function_preClaim(uint256 season_id_
) internalreturns (uint256)
{
require(claimed_rewards[season_id_][msg.sender] ==0, "REWARD CLAIMED");
//require(access_pass.isVerified(msg.sender), "MUST HAVE VERIFIED AN ACCESS PASS");
Season storage _season = seasons[season_id_];
require(isSeasonClaimingActive(_season, block.timestamp), "SEASON_CLAIM_ENDED");
uint256 _reward = season_rewards[season_id_][msg.sender];
require(_reward >0, "MUST HAVE A NON ZERO REWARD");
_season.remaining_reward_amount -= _reward;
claimed_rewards[season_id_][msg.sender] = _reward;
return _reward;
}
///@notice Claim tokens to msg.sender///@dev Callable only on seasons which have been finalized and whose claim duration has not elapsed.///@param season_id_ The season to claim reward tokens from.functionclaimReward(uint256 season_id_
) external{
uint256 _reward = _preClaim(season_id_);
bool transfer_success = token.transfer(msg.sender, _reward);
require(transfer_success, "FAILED TRANSFER");
}
///@notice Stake tokens claimed.///@dev Callable only on seasons which have been finalized and whose claim duration has not elapsed.///@param season_id_ The season to claim reward tokens from.functionstakeReward(uint256 season_id_
) external{
uint256 _reward = _preClaim(season_id_);
token.approve(address(staking_pool), _reward);
staking_pool.stakeFor(msg.sender, _reward);
emit StakedRewards(msg.sender, _reward);
}
///@notice get reward tokens claimable by a player in the specified season.///@param season_id_ The season to get reward tokens from.functiongetClaimableReward(uint256 season_id_
) publicviewreturns(uint256 _reward)
{
_reward = season_rewards[season_id_][msg.sender] - claimed_rewards[season_id_][msg.sender];
Season storage _season = seasons[season_id_];
if( !isSeasonClaimingActive(_season, block.timestamp) ) //|| //!access_pass.isVerified(msg.sender))
{
_reward =0;
}
}
/// @notice Transfer tokens that have been sent to this contract by mistake./// @dev Only callable by address with Global Admin permissions. Cannot be called to withdraw emissions tokens./// @param tokenAddress_ The address of the token to recover/// @param tokenAmount_ The amount of the token to recoverfunctionrecoverERC20(address tokenAddress_, uint256 tokenAmount_) externalisGlobalAdmin{
IERC20(tokenAddress_).transfer(msg.sender, tokenAmount_);
}
}