From 41cc7daa464a5796459f7ba721ba7ff6b16e8645 Mon Sep 17 00:00:00 2001 From: Lucian Hymer Date: Wed, 26 Jun 2024 11:06:32 -0600 Subject: [PATCH] feat(contracts): add IScrollBadgeUpgradeable --- src/Errors.sol | 1 + src/badge/examples/ScrollBadgePowerRank.sol | 23 +++++++++++++++---- .../extensions/IScrollBadgeUpgradeable.sol | 18 +++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 src/badge/extensions/IScrollBadgeUpgradeable.sol diff --git a/src/Errors.sol b/src/Errors.sol index ab3039e..8e52ff4 100644 --- a/src/Errors.sol +++ b/src/Errors.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.19; error Unauthorized(); +error CannotUpgrade(bytes32 uid); // attestation errors // note: these don't include the uid since it is not known prior to the attestation. diff --git a/src/badge/examples/ScrollBadgePowerRank.sol b/src/badge/examples/ScrollBadgePowerRank.sol index 1e492da..53cf075 100644 --- a/src/badge/examples/ScrollBadgePowerRank.sol +++ b/src/badge/examples/ScrollBadgePowerRank.sol @@ -13,7 +13,8 @@ import {ScrollBadgeCustomPayload} from "../extensions/ScrollBadgeCustomPayload.s import {ScrollBadgeNoExpiry} from "../extensions/ScrollBadgeNoExpiry.sol"; import {ScrollBadgeNonRevocable} from "../extensions/ScrollBadgeNonRevocable.sol"; import {ScrollBadgeSingleton} from "../extensions/ScrollBadgeSingleton.sol"; -import {Unauthorized} from "../../Errors.sol"; +import {IScrollBadgeUpgradeable} from "../extensions/IScrollBadgeUpgradeable.sol"; +import {Unauthorized, CannotUpgrade} from "../../Errors.sol"; string constant SCROLL_BADGE_POWER_RANK_SCHEMA = "uint256 firstTxTimestamp"; @@ -28,10 +29,9 @@ contract ScrollBadgePowerRank is ScrollBadgeCustomPayload, ScrollBadgeNoExpiry, ScrollBadgeNonRevocable, - ScrollBadgeSingleton + ScrollBadgeSingleton, + IScrollBadgeUpgradeable { - error CannotUpgrade(); - event Upgrade(uint256 oldRank, uint256 newRank); // badge UID => current rank @@ -92,6 +92,19 @@ contract ScrollBadgePowerRank is return SCROLL_BADGE_POWER_RANK_SCHEMA; } + /// @inheritdoc IScrollBadgeUpgradeable + function canUpgrade(bytes32 uid) external view returns (bool) { + Attestation memory badge = getAndValidateBadge(uid); + + bytes memory payload = getPayload(badge); + (uint256 firstTxTimestamp) = decodePayloadData(payload); + uint256 newRank = timestampToRank(firstTxTimestamp); + + uint256 oldRank = badgeRank[uid]; + return newRank > oldRank; + } + + /// @inheritdoc IScrollBadgeUpgradeable function upgrade(bytes32 uid) external { Attestation memory badge = getAndValidateBadge(uid); @@ -105,7 +118,7 @@ contract ScrollBadgePowerRank is uint256 oldRank = badgeRank[uid]; if (newRank <= oldRank) { - revert CannotUpgrade(); + revert CannotUpgrade(uid); } badgeRank[uid] = newRank; diff --git a/src/badge/extensions/IScrollBadgeUpgradeable.sol b/src/badge/extensions/IScrollBadgeUpgradeable.sol new file mode 100644 index 0000000..f554073 --- /dev/null +++ b/src/badge/extensions/IScrollBadgeUpgradeable.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +/// @title IScrollBadgeUpgradeable +/// @notice This interface defines functions to facilitate badge upgrades. +interface IScrollBadgeUpgradeable { + /// @notice Checks if a badge can be upgraded. + /// @param uid The unique identifier of the badge. + /// @return True if the badge can be upgraded, false otherwise. + function canUpgrade(bytes32 uid) external view returns (bool); + + /// @notice Upgrades a badge. + /// @param uid The unique identifier of the badge. + /// @dev Should revert with CannotUpgrade (from Errors.sol) if the badge cannot be upgraded. + /// @dev Should emit an Upgrade event (custom defined) if the upgrade is successful. + function upgrade(bytes32 uid) external; +}