-
Notifications
You must be signed in to change notification settings - Fork 8
/
Claimable.sol
134 lines (108 loc) · 4.73 KB
/
Claimable.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IClaimable } from "pt-v5-claimable-interface/interfaces/IClaimable.sol";
import { PrizePool } from "pt-v5-prize-pool/PrizePool.sol";
import { HookManager } from "./HookManager.sol";
/// @title PoolTogether V5 Claimable Vault Extension
/// @author G9 Software Inc.
/// @notice Provides an interface for Claimer contracts to interact with a vault in PoolTogether
/// V5 while allowing each account to set and manage prize hooks that are called when they win.
abstract contract Claimable is HookManager, IClaimable {
////////////////////////////////////////////////////////////////////////////////
// Public Constants and Variables
////////////////////////////////////////////////////////////////////////////////
/// @notice The gas to give to each of the before and after prize claim hooks.
/// @dev This should be enough gas to mint an NFT if needed.
uint24 public constant HOOK_GAS = 150_000;
/// @notice Address of the PrizePool that computes prizes.
PrizePool public immutable prizePool;
/// @notice Address of the claimer.
address public claimer;
////////////////////////////////////////////////////////////////////////////////
// Errors
////////////////////////////////////////////////////////////////////////////////
/// @notice Thrown when the Prize Pool is set to the zero address.
error PrizePoolZeroAddress();
/// @notice Thrown when the Claimer is set to the zero address.
error ClaimerZeroAddress();
/// @notice Thrown when a prize is claimed for the zero address.
error ClaimRecipientZeroAddress();
/// @notice Thrown when the caller is not the prize claimer.
/// @param caller The caller address
/// @param claimer The claimer address
error CallerNotClaimer(address caller, address claimer);
////////////////////////////////////////////////////////////////////////////////
// Modifiers
////////////////////////////////////////////////////////////////////////////////
/// @notice Requires the caller to be the claimer.
modifier onlyClaimer() {
if (msg.sender != claimer) revert CallerNotClaimer(msg.sender, claimer);
_;
}
////////////////////////////////////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////////////////////////////////////
/// @notice Claimable constructor
/// @param prizePool_ The prize pool to claim prizes from
/// @param claimer_ The address allowed to claim prizes on behalf of winners
constructor(PrizePool prizePool_, address claimer_) {
if (address(prizePool_) == address(0)) revert PrizePoolZeroAddress();
prizePool = prizePool_;
_setClaimer(claimer_);
}
////////////////////////////////////////////////////////////////////////////////
// IClaimable Implementation
////////////////////////////////////////////////////////////////////////////////
/// @inheritdoc IClaimable
/// @dev Also calls the before and after claim hooks if set by the winner.
function claimPrize(
address _winner,
uint8 _tier,
uint32 _prizeIndex,
uint96 _reward,
address _rewardRecipient
) external onlyClaimer returns (uint256) {
address recipient;
if (_hooks[_winner].useBeforeClaimPrize) {
recipient = _hooks[_winner].implementation.beforeClaimPrize{ gas: HOOK_GAS }(
_winner,
_tier,
_prizeIndex,
_reward,
_rewardRecipient
);
} else {
recipient = _winner;
}
if (recipient == address(0)) revert ClaimRecipientZeroAddress();
uint256 prizeTotal = prizePool.claimPrize(
_winner,
_tier,
_prizeIndex,
recipient,
_reward,
_rewardRecipient
);
if (_hooks[_winner].useAfterClaimPrize) {
_hooks[_winner].implementation.afterClaimPrize{ gas: HOOK_GAS }(
_winner,
_tier,
_prizeIndex,
prizeTotal,
recipient
);
}
return prizeTotal;
}
////////////////////////////////////////////////////////////////////////////////
// Internal Helpers
////////////////////////////////////////////////////////////////////////////////
/// @notice Set claimer address.
/// @dev Will revert if `_claimer` is address zero.
/// @param _claimer Address of the claimer
function _setClaimer(address _claimer) internal {
if (_claimer == address(0)) revert ClaimerZeroAddress();
claimer = _claimer;
emit ClaimerSet(_claimer);
}
}