ClankerFeeLocker
0x88db2340be5991b2b5fca2baee39b5ce048cd70c
Verification
Verified
v0.8.28+commit.7893614a
Type
Contract
2,663 bytes
ABI entries
22
5 read · 5 write
License
none
Contract information
- Address
- 0x88db2340be5991b2b5fca2baee39b5ce048cd70c
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.28+commit.7893614a
- Optimization
- Enabled
- Creator
- 0x2f2F61d1d3…E8b487A093
- Creation tx
- 0xf9d439ba4b…aefd6899aa
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (5)
allowedDepositors(address) → bool
availableFees(address, address) → uint256
feesToClaim(address, address) → uint256
owner() → address
supportsInterface(bytes4) → bool
Events (5)
AddDepositorClaimTokensClaimTokensPermissionedOwnershipTransferredStoreTokens
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "owner_",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "NoFeesToClaim",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "OwnableInvalidOwner",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "OwnableUnauthorizedAccount",
"type": "error"
},
{
"inputs": [],
"name": "ReentrancyGuardReentrantCall",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "SafeERC20FailedOperation",
"type": "error"
},
{
"inputs": [],
"name": "Unauthorized",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "depositor",
"type": "address"
}
],
"name": "AddDepositor",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "feeOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amountClaimed",
"type": "uint256"
}
],
"name": "ClaimTokens",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "feeOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amountClaimed",
"type": "uint256"
}
],
"name": "ClaimTokensPermissioned",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "feeOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "balance",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "StoreTokens",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "depositor",
"type": "address"
}
],
"name": "addDepositor",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "depositor",
"type": "address"
}
],
"name": "allowedDepositors",
"outputs": [
{
"internalType": "bool",
"name": "isAllowed",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "feeOwner",
"type": "address"
},
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "availableFees",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "feeOwner",
"type": "address"
},
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "claim",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "feeOwner",
"type": "address"
},
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "feesToClaim",
"outputs": [
{
"internalType": "uint256",
"name": "balance",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "feeOwner",
"type": "address"
},
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "storeFees",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import {IClankerFeeLocker} from "./interfaces/IClankerFeeLocker.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract ClankerFeeLocker is IClankerFeeLocker, ReentrancyGuard, Ownable {
mapping(address feeOwner => mapping(address token => uint256 balance)) public feesToClaim;
mapping(address depositor => bool isAllowed) public allowedDepositors;
constructor(address owner_) Ownable(owner_) {}
function addDepositor(address depositor) external onlyOwner {
allowedDepositors[depositor] = true;
emit AddDepositor(depositor);
}
function storeFees(address feeOwner, address token, uint256 amount) external nonReentrant {
if (!allowedDepositors[msg.sender]) revert Unauthorized();
// use balance deltas to support fee on transfer and weird tokens
uint256 balanceBefore = IERC20(token).balanceOf(address(this));
SafeERC20.safeTransferFrom(IERC20(token), msg.sender, address(this), amount);
uint256 balanceAfter = IERC20(token).balanceOf(address(this));
uint256 receivedAmount = balanceAfter - balanceBefore;
feesToClaim[feeOwner][token] += receivedAmount;
emit StoreTokens(msg.sender, feeOwner, token, feesToClaim[feeOwner][token], amount);
}
// helper function to check available fees
function availableFees(address feeOwner, address token) external view returns (uint256) {
return feesToClaim[feeOwner][token];
}
// claim fees on behalf of a feeOwner
function claim(address feeOwner, address token) external nonReentrant {
uint256 balance = feesToClaim[feeOwner][token];
if (balance == 0) revert NoFeesToClaim();
// debit account
feesToClaim[feeOwner][token] = 0;
// transfer funds
SafeERC20.safeTransfer(IERC20(token), feeOwner, balance);
emit ClaimTokens(feeOwner, token, balance);
}
function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
return interfaceId == type(IClankerFeeLocker).interfaceId;
}
}
Chain explorer6281msChain node76ms