文件 1 的 12:Address.sol
pragma solidity ^0.7.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 12:IERC20.sol
pragma solidity ^0.7.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 3 的 12:IERC20Ext.sol
pragma solidity 0.7.6;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IERC20Ext is IERC20 {
function decimals() external view returns (uint8 digits);
}
文件 4 的 12:IPool.sol
pragma solidity 0.7.6;
import {IERC20Ext} from '@kyber.network/utils-sc/contracts/IERC20Ext.sol';
interface IPool {
event AuthorizedStrategy(address indexed strategy);
event UnauthorizedStrategy(address indexed strategy);
event Paused(address indexed sender);
event Unpaused(address indexed sender);
event WithdrawToken(
IERC20Ext indexed token,
address indexed sender,
address indexed recipient,
uint256 amount
);
function pause() external;
function unpause() external;
function authorizeStrategies(address[] calldata strategies) external;
function unauthorizeStrategies(address[] calldata strategies) external;
function withdrawFunds(
IERC20Ext[] calldata tokens,
uint256[] calldata amounts,
address payable recipient
) external;
function isPaused() external view returns (bool);
function isAuthorizedStrategy(address strategy) external view returns (bool);
function getAuthorizedStrategiesLength() external view returns (uint256);
function getAuthorizedStrategyAt(uint256 index) external view returns (address);
function getAllAuthorizedStrategies()
external view returns (address[] memory strategies);
}
文件 5 的 12:IRewardsDistributor.sol
pragma solidity 0.7.6;
import {IERC20Ext} from '@kyber.network/utils-sc/contracts/IERC20Ext.sol';
interface IRewardsDistributor {
event Claimed(
uint256 indexed cycle,
address indexed user,
IERC20Ext[] tokens,
uint256[] claimAmounts
);
function claim(
uint256 cycle,
uint256 index,
address user,
IERC20Ext[] calldata tokens,
uint256[] calldata cumulativeAmounts,
bytes32[] calldata merkleProof
) external returns (uint256[] memory claimAmounts);
function isValidClaim(
uint256 cycle,
uint256 index,
address user,
IERC20Ext[] calldata tokens,
uint256[] calldata cumulativeAmounts,
bytes32[] calldata merkleProof
) external view returns (bool);
function getClaimedAmounts(address user, IERC20Ext[] calldata tokens)
external
view
returns (uint256[] memory userClaimedAmounts);
}
文件 6 的 12:MerkleProof.sol
pragma solidity ^0.7.0;
library MerkleProof {
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
return computedHash == root;
}
}
文件 7 的 12:PermissionAdmin.sol
pragma solidity 0.7.6;
abstract contract PermissionAdmin {
address public admin;
address public pendingAdmin;
event AdminClaimed(address newAdmin, address previousAdmin);
event TransferAdminPending(address pendingAdmin);
constructor(address _admin) {
require(_admin != address(0), "admin 0");
admin = _admin;
}
modifier onlyAdmin() {
require(msg.sender == admin, "only admin");
_;
}
function transferAdmin(address newAdmin) public onlyAdmin {
require(newAdmin != address(0), "new admin 0");
emit TransferAdminPending(newAdmin);
pendingAdmin = newAdmin;
}
function transferAdminQuickly(address newAdmin) public onlyAdmin {
require(newAdmin != address(0), "admin 0");
emit TransferAdminPending(newAdmin);
emit AdminClaimed(newAdmin, admin);
admin = newAdmin;
}
function claimAdmin() public {
require(pendingAdmin == msg.sender, "not pending");
emit AdminClaimed(pendingAdmin, admin);
admin = pendingAdmin;
pendingAdmin = address(0);
}
}
文件 8 的 12:ReentrancyGuard.sol
pragma solidity ^0.7.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 9 的 12:RewardsDistributor.sol
pragma solidity 0.7.6;
pragma abicoder v2;
import {ReentrancyGuard} from '@openzeppelin/contracts/utils/ReentrancyGuard.sol';
import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import {MerkleProof} from '@openzeppelin/contracts/cryptography/MerkleProof.sol';
import {Utils} from '@kyber.network/utils-sc/contracts/Utils.sol';
import {PermissionAdmin} from '@kyber.network/utils-sc/contracts/PermissionAdmin.sol';
import {IPool} from '../interfaces/liquidation/IPool.sol';
import {IERC20Ext, IRewardsDistributor} from '../interfaces/rewardDistribution/IRewardsDistributor.sol';
contract RewardsDistributor is IRewardsDistributor, PermissionAdmin, ReentrancyGuard, Utils {
using SafeERC20 for IERC20Ext;
using SafeMath for uint256;
struct MerkleData {
uint256 cycle;
bytes32 root;
string contentHash;
}
MerkleData private merkleData;
mapping(address => mapping(IERC20Ext => uint256)) public claimedAmounts;
event RootUpdated(uint256 indexed cycle, bytes32 root, string contentHash);
constructor(address admin) PermissionAdmin(admin) {}
receive() external payable {}
function getMerkleData() external view returns (MerkleData memory) {
return merkleData;
}
function claim(
uint256 cycle,
uint256 index,
address user,
IERC20Ext[] calldata tokens,
uint256[] calldata cumulativeAmounts,
bytes32[] calldata merkleProof
) external override nonReentrant returns (uint256[] memory claimAmounts) {
require(
isValidClaim(cycle, index, user, tokens, cumulativeAmounts, merkleProof),
'invalid claim data'
);
claimAmounts = new uint256[](tokens.length);
for (uint256 i = 0; i < tokens.length; i++) {
if (cumulativeAmounts[i] == 0) continue;
uint256 claimable = cumulativeAmounts[i].sub(claimedAmounts[user][tokens[i]]);
if (claimable == 0) continue;
claimedAmounts[user][tokens[i]] = cumulativeAmounts[i];
claimAmounts[i] = claimable;
if (tokens[i] == ETH_TOKEN_ADDRESS) {
(bool success, ) = user.call{value: claimable}('');
require(success, 'eth transfer failed');
} else {
tokens[i].safeTransfer(user, claimable);
}
}
emit Claimed(cycle, user, tokens, claimAmounts);
}
function proposeRoot(
uint256 cycle,
bytes32 root,
string calldata contentHash
) external onlyAdmin {
require(cycle == merkleData.cycle.add(1), 'incorrect cycle');
merkleData.cycle = cycle;
merkleData.root = root;
merkleData.contentHash = contentHash;
emit RootUpdated(cycle, root, contentHash);
}
function pullFundsFromTreasury(
IPool treasuryPool,
IERC20Ext[] calldata tokens,
uint256[] calldata amounts
)
external
onlyAdmin
{
treasuryPool.withdrawFunds(tokens, amounts, payable(address(this)));
}
function isValidClaim(
uint256 cycle,
uint256 index,
address user,
IERC20Ext[] calldata tokens,
uint256[] calldata cumulativeAmounts,
bytes32[] calldata merkleProof
) public view override returns (bool) {
if (cycle != merkleData.cycle) return false;
if (tokens.length != cumulativeAmounts.length) return false;
bytes32 node = keccak256(abi.encode(cycle, index, user, tokens, cumulativeAmounts));
return MerkleProof.verify(merkleProof, merkleData.root, node);
}
function getClaimedAmounts(address user, IERC20Ext[] calldata tokens)
public
view
override
returns (uint256[] memory userClaimedAmounts)
{
userClaimedAmounts = new uint256[](tokens.length);
for (uint256 i = 0; i < tokens.length; i++) {
userClaimedAmounts[i] = claimedAmounts[user][tokens[i]];
}
}
function encodeClaim(
uint256 cycle,
uint256 index,
address account,
IERC20Ext[] calldata tokens,
uint256[] calldata cumulativeAmounts
) external pure returns (bytes memory encodedData, bytes32 encodedDataHash) {
require(tokens.length == cumulativeAmounts.length, 'bad tokens and amounts length');
encodedData = abi.encode(cycle, index, account, tokens, cumulativeAmounts);
encodedDataHash = keccak256(encodedData);
}
}
文件 10 的 12:SafeERC20.sol
pragma solidity ^0.7.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 11 的 12:SafeMath.sol
pragma solidity ^0.7.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 12 的 12:Utils.sol
pragma solidity 0.7.6;
import "./IERC20Ext.sol";
abstract contract Utils {
IERC20Ext internal constant ETH_TOKEN_ADDRESS = IERC20Ext(
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
);
IERC20Ext internal constant USDT_TOKEN_ADDRESS = IERC20Ext(
0xdAC17F958D2ee523a2206206994597C13D831ec7
);
IERC20Ext internal constant DAI_TOKEN_ADDRESS = IERC20Ext(
0x6B175474E89094C44Da98b954EedeAC495271d0F
);
IERC20Ext internal constant USDC_TOKEN_ADDRESS = IERC20Ext(
0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
);
IERC20Ext internal constant WBTC_TOKEN_ADDRESS = IERC20Ext(
0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599
);
IERC20Ext internal constant KNC_TOKEN_ADDRESS = IERC20Ext(
0xdd974D5C2e2928deA5F71b9825b8b646686BD200
);
uint256 public constant BPS = 10000;
uint256 internal constant PRECISION = (10**18);
uint256 internal constant MAX_QTY = (10**28);
uint256 internal constant MAX_RATE = (PRECISION * 10**7);
uint256 internal constant MAX_DECIMALS = 18;
uint256 internal constant ETH_DECIMALS = 18;
uint256 internal constant MAX_ALLOWANCE = uint256(-1);
mapping(IERC20Ext => uint256) internal decimals;
function getSetDecimals(IERC20Ext token) internal returns (uint256 tokenDecimals) {
tokenDecimals = getDecimalsConstant(token);
if (tokenDecimals > 0) return tokenDecimals;
tokenDecimals = decimals[token];
if (tokenDecimals == 0) {
tokenDecimals = token.decimals();
decimals[token] = tokenDecimals;
}
}
function getBalance(IERC20Ext token, address user) internal view returns (uint256) {
if (token == ETH_TOKEN_ADDRESS) {
return user.balance;
} else {
return token.balanceOf(user);
}
}
function getDecimals(IERC20Ext token) internal view returns (uint256 tokenDecimals) {
tokenDecimals = getDecimalsConstant(token);
if (tokenDecimals > 0) return tokenDecimals;
tokenDecimals = decimals[token];
return (tokenDecimals > 0) ? tokenDecimals : token.decimals();
}
function calcDestAmount(
IERC20Ext src,
IERC20Ext dest,
uint256 srcAmount,
uint256 rate
) internal view returns (uint256) {
return calcDstQty(srcAmount, getDecimals(src), getDecimals(dest), rate);
}
function calcSrcAmount(
IERC20Ext src,
IERC20Ext dest,
uint256 destAmount,
uint256 rate
) internal view returns (uint256) {
return calcSrcQty(destAmount, getDecimals(src), getDecimals(dest), rate);
}
function calcDstQty(
uint256 srcQty,
uint256 srcDecimals,
uint256 dstDecimals,
uint256 rate
) internal pure returns (uint256) {
require(srcQty <= MAX_QTY, "srcQty > MAX_QTY");
require(rate <= MAX_RATE, "rate > MAX_RATE");
if (dstDecimals >= srcDecimals) {
require((dstDecimals - srcDecimals) <= MAX_DECIMALS, "dst - src > MAX_DECIMALS");
return (srcQty * rate * (10**(dstDecimals - srcDecimals))) / PRECISION;
} else {
require((srcDecimals - dstDecimals) <= MAX_DECIMALS, "src - dst > MAX_DECIMALS");
return (srcQty * rate) / (PRECISION * (10**(srcDecimals - dstDecimals)));
}
}
function calcSrcQty(
uint256 dstQty,
uint256 srcDecimals,
uint256 dstDecimals,
uint256 rate
) internal pure returns (uint256) {
require(dstQty <= MAX_QTY, "dstQty > MAX_QTY");
require(rate <= MAX_RATE, "rate > MAX_RATE");
uint256 numerator;
uint256 denominator;
if (srcDecimals >= dstDecimals) {
require((srcDecimals - dstDecimals) <= MAX_DECIMALS, "src - dst > MAX_DECIMALS");
numerator = (PRECISION * dstQty * (10**(srcDecimals - dstDecimals)));
denominator = rate;
} else {
require((dstDecimals - srcDecimals) <= MAX_DECIMALS, "dst - src > MAX_DECIMALS");
numerator = (PRECISION * dstQty);
denominator = (rate * (10**(dstDecimals - srcDecimals)));
}
return (numerator + denominator - 1) / denominator;
}
function calcRateFromQty(
uint256 srcAmount,
uint256 destAmount,
uint256 srcDecimals,
uint256 dstDecimals
) internal pure returns (uint256) {
require(srcAmount <= MAX_QTY, "srcAmount > MAX_QTY");
require(destAmount <= MAX_QTY, "destAmount > MAX_QTY");
if (dstDecimals >= srcDecimals) {
require((dstDecimals - srcDecimals) <= MAX_DECIMALS, "dst - src > MAX_DECIMALS");
return ((destAmount * PRECISION) / ((10**(dstDecimals - srcDecimals)) * srcAmount));
} else {
require((srcDecimals - dstDecimals) <= MAX_DECIMALS, "src - dst > MAX_DECIMALS");
return ((destAmount * PRECISION * (10**(srcDecimals - dstDecimals))) / srcAmount);
}
}
function getDecimalsConstant(IERC20Ext token) internal pure returns (uint256) {
if (token == ETH_TOKEN_ADDRESS) {
return ETH_DECIMALS;
} else if (token == USDT_TOKEN_ADDRESS) {
return 6;
} else if (token == DAI_TOKEN_ADDRESS) {
return 18;
} else if (token == USDC_TOKEN_ADDRESS) {
return 6;
} else if (token == WBTC_TOKEN_ADDRESS) {
return 8;
} else if (token == KNC_TOKEN_ADDRESS) {
return 18;
} else {
return 0;
}
}
function minOf(uint256 x, uint256 y) internal pure returns (uint256) {
return x > y ? y : x;
}
}
{
"compilationTarget": {
"contracts/reward/RewardsDistributor.sol": "RewardsDistributor"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"}],"name":"AdminClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"cycle","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"contract IERC20Ext[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"claimAmounts","type":"uint256[]"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"cycle","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"},{"indexed":false,"internalType":"string","name":"contentHash","type":"string"}],"name":"RootUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pendingAdmin","type":"address"}],"name":"TransferAdminPending","type":"event"},{"inputs":[],"name":"BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"cycle","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"contract IERC20Ext[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"cumulativeAmounts","type":"uint256[]"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"claim","outputs":[{"internalType":"uint256[]","name":"claimAmounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"contract IERC20Ext","name":"","type":"address"}],"name":"claimedAmounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"cycle","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"contract IERC20Ext[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"cumulativeAmounts","type":"uint256[]"}],"name":"encodeClaim","outputs":[{"internalType":"bytes","name":"encodedData","type":"bytes"},{"internalType":"bytes32","name":"encodedDataHash","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"contract IERC20Ext[]","name":"tokens","type":"address[]"}],"name":"getClaimedAmounts","outputs":[{"internalType":"uint256[]","name":"userClaimedAmounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMerkleData","outputs":[{"components":[{"internalType":"uint256","name":"cycle","type":"uint256"},{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"string","name":"contentHash","type":"string"}],"internalType":"struct RewardsDistributor.MerkleData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"cycle","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"contract IERC20Ext[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"cumulativeAmounts","type":"uint256[]"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"isValidClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"cycle","type":"uint256"},{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"string","name":"contentHash","type":"string"}],"name":"proposeRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPool","name":"treasuryPool","type":"address"},{"internalType":"contract IERC20Ext[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"pullFundsFromTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferAdminQuickly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]