Skip to content

Commit 708669a

Browse files
authored
feat: Add claimFor method to AcrossMerkleDistributor (#200)
* feat: Update AcrossMerkleDistributor deployment * Update deployments.json * feat: Add claimFor method to AcrossMerkleDistributor Allows a whitelisted account to claim on behalf of a user. Can be used to atomically claim and perform some action for a user, such as claim and stake. * Update yarn.lock * Update package.json * Whitelisted claimer only works for claimFor * Update MerkleDistributor.ts
1 parent 1b6a742 commit 708669a

File tree

5 files changed

+216
-678
lines changed

5 files changed

+216
-678
lines changed

contracts/merkle-distributor/AcrossMerkleDistributor.sol

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,31 @@
22
pragma solidity ^0.8.0;
33

44
import "@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
*/
1012
contract 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
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@across-protocol/contracts-v2",
3-
"version": "1.0.6",
3+
"version": "1.0.7",
44
"author": "UMA Team",
55
"license": "AGPL-3.0",
66
"repository": {
@@ -37,7 +37,7 @@
3737
"@openzeppelin/contracts": "^4.7.3",
3838
"@uma/common": "^2.28.0",
3939
"@uma/contracts-node": "^0.3.18",
40-
"@uma/core": "^2.40.0",
40+
"@uma/core": "^2.41.0",
4141
"@uma/merkle-distributor": "^1.3.38",
4242
"arb-bridge-eth": "^0.7.4",
4343
"arb-bridge-peripherals": "^1.0.5"

0 commit comments

Comments
 (0)