22pragma solidity ^ 0.8.0 ;
33
44import "@uma/core/contracts/merkle-distributor/implementation/MerkleDistributor.sol " ;
5+ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol " ;
6+ import "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
57
68/**
79 * @title Extended MerkleDistributor contract.
810 * @notice Adds additional constraints governing who can claim leaves from merkle windows.
911 */
1012contract AcrossMerkleDistributor is MerkleDistributor {
11- // Addresses that can claim on user's behalf. Useful to get around the requirement that claim recipient
12- // must also be claimer.
13+ using SafeERC20 for IERC20 ;
14+
15+ // Addresses that can claim on user's behalf.
1316 mapping (address => bool ) public whitelistedClaimers;
1417
1518 /****************************************
1619 * EVENTS
1720 ****************************************/
1821 event WhitelistedClaimer (address indexed claimer , bool indexed whitelist );
22+ event ClaimFor (
23+ address indexed caller ,
24+ uint256 windowIndex ,
25+ address indexed account ,
26+ uint256 accountIndex ,
27+ uint256 amount ,
28+ address indexed rewardToken
29+ );
1930
2031 /****************************
2132 * ADMIN FUNCTIONS
@@ -39,26 +50,47 @@ contract AcrossMerkleDistributor is MerkleDistributor {
3950 /**
4051 * @notice Batch claims to reduce gas versus individual submitting all claims. Method will fail
4152 * if any individual claims within the batch would fail.
42- * @dev All claim recipients must be equal to msg.sender or claimer must be whitelisted .
53+ * @dev All claim recipients must be equal to msg.sender.
4354 * @param claims array of claims to claim.
4455 */
4556 function claimMulti (Claim[] memory claims ) public override {
46- if (! whitelistedClaimers[msg .sender ]) {
47- uint256 claimCount = claims.length ;
48- for (uint256 i = 0 ; i < claimCount; i++ ) {
49- require (claims[i].account == msg .sender , "invalid claimer " );
50- }
57+ uint256 claimCount = claims.length ;
58+ for (uint256 i = 0 ; i < claimCount; i++ ) {
59+ require (claims[i].account == msg .sender , "invalid claimer " );
5160 }
5261 super .claimMulti (claims);
5362 }
5463
5564 /**
5665 * @notice Claim amount of reward tokens for account, as described by Claim input object.
57- * @dev Claim recipient must be equal to msg.sender or caller must be whitelisted .
66+ * @dev Claim recipient must be equal to msg.sender.
5867 * @param _claim claim object describing amount, accountIndex, account, window index, and merkle proof.
5968 */
6069 function claim (Claim memory _claim ) public override {
61- require (whitelistedClaimers[ msg . sender ] || _claim.account == msg .sender , "invalid claimer " );
70+ require (_claim.account == msg .sender , "invalid claimer " );
6271 super .claim (_claim);
6372 }
73+
74+ /**
75+ * @notice Executes merkle leaf claim on behaf of user. This can only be called by a trusted
76+ * claimer address. This function is designed to be called atomically with other transactions
77+ * that ultimately return the claimed amount to the rightful recipient. For example,
78+ * AcceleratingDistributor could call this function and then stake atomically on behalf of the user.
79+ * @dev Caller must be in whitelistedClaimers struct set to "true".
80+ * @param _claim leaf to claim.
81+ */
82+
83+ function claimFor (Claim memory _claim ) public {
84+ require (whitelistedClaimers[msg .sender ], "unwhitelisted claimer " );
85+ _verifyAndMarkClaimed (_claim);
86+ merkleWindows[_claim.windowIndex].rewardToken.safeTransfer (msg .sender , _claim.amount);
87+ emit ClaimFor (
88+ msg .sender ,
89+ _claim.windowIndex,
90+ _claim.account,
91+ _claim.accountIndex,
92+ _claim.amount,
93+ address (merkleWindows[_claim.windowIndex].rewardToken)
94+ );
95+ }
6496}
0 commit comments