Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Cross-Chain Transactions
Loading...
Loading
Contract Name:
RecoveryHub
Compiler Version
v0.8.25+commit.b61c2a91
Contract Source Code (Solidity Standard Json-Input format)
/**
* SPDX-License-Identifier: LicenseRef-Aktionariat
*
* MIT License with Automated License Fee Payments
*
* Copyright (c) 2022 Aktionariat AG (aktionariat.com)
*
* Permission is hereby granted to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - All automated license fee payments integrated into this and related Software
* are preserved.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
pragma solidity ^0.8.0;
import "./IRecoveryHub.sol";
import "./IRecoverable.sol";
import "../ERC20/IERC20.sol";
import "../utils/SafeERC20.sol";
contract RecoveryHub is IRecoveryHub {
using SafeERC20 for IERC20;
// A struct that represents a claim made
struct Claim {
address claimant; // the person who created the claim
uint256 collateral; // the amount of collateral deposited
uint256 timestamp; // the timestamp of the block in which the claim was made
IERC20 currencyUsed; // The currency (XCHF) can be updated, we record the currency used for every request
}
mapping(IRecoverable => mapping (address => Claim)) public claims; // there can be at most one claim per token and claimed address
mapping(address => bool) public recoveryDisabled; // disable claimability (e.g. for long term storage)
event ClaimMade(IRecoverable indexed token, address indexed lostAddress, address indexed claimant, uint256 balance);
event ClaimCleared(IRecoverable indexed token, address indexed lostAddress, uint256 collateral);
event ClaimDeleted(IRecoverable indexed token, address indexed lostAddress, address indexed claimant, uint256 collateral);
event ClaimResolved(IRecoverable indexed token, address indexed lostAddress, address indexed claimant, uint256 collateral);
function setRecoverable(bool enabled) external override {
recoveryDisabled[msg.sender] = !enabled;
}
/**
* Some users might want to disable claims for their address completely.
* For example if they use a deep cold storage solution or paper wallet.
*/
function isRecoverable(address target) public view returns (bool) {
return !recoveryDisabled[target];
}
/** Anyone can declare that the private key to a certain address was lost by calling declareLost
* providing a deposit/collateral. There are three possibilities of what can happen with the claim:
* 1) The claim period expires and the claimant can get the deposit and the shares back by calling recover
* 2) The "lost" private key is used at any time to call clearClaim. In that case, the claim is deleted and
* the deposit sent to the shareholder (the owner of the private key). It is recommended to call recover
* whenever someone transfers funds to let claims be resolved automatically when the "lost" private key is
* used again.
* 3) The owner deletes the claim and assigns the deposit to the claimant. This is intended to be used to resolve
* disputes. Generally, using this function implies that you have to trust the issuer of the tokens to handle
* the situation well. As a rule of thumb, the contract owner should assume the owner of the lost address to be the
* rightful owner of the deposit.
* It is highly recommended that the owner observes the claims made and informs the owners of the claimed addresses
* whenever a claim is made for their address (this of course is only possible if they are known to the owner, e.g.
* through a shareholder register).
*/
function declareLost(IRecoverable token, IERC20 collateralType, address lostAddress) external {
if(recoveryDisabled[lostAddress]) {
revert RecoveryHub_RecoveryDisabled(lostAddress);
}
uint256 collateralRate = IRecoverable(token).getCollateralRate(collateralType);
if (collateralRate == 0) {
// if the there is no rate the collateral isn't accepted
revert RecoveryHub_BadCollateral(collateralType);
}
uint256 balance = IERC20(token).balanceOf(lostAddress);
if (balance == 0) {
// if lost address has no balance, there also nothing to recover
revert RecoveryHub_NothingToRecover(token, lostAddress);
}
uint256 collateral = balance * collateralRate;
IERC20 currency = IERC20(collateralType);
if (claims[token][lostAddress].collateral > 0) {
revert RecoveryHub_AlreadyClaimed(token, lostAddress);
}
claims[token][lostAddress] = Claim({
claimant: msg.sender,
collateral: collateral,
// rely on time stamp is ok, no exact time stamp needed
// solhint-disable-next-line not-rely-on-time
timestamp: block.timestamp,
currencyUsed: collateralType
});
emit ClaimMade(token, lostAddress, msg.sender, balance);
// errors like no allowance/no balance revert generally in the transferFrom
currency.safeTransferFrom(msg.sender, address(this), collateral);
IRecoverable(token).notifyClaimMade(lostAddress);
}
function getClaimant(IRecoverable token, address lostAddress) external view returns (address) {
return claims[token][lostAddress].claimant;
}
function getCollateral(IRecoverable token, address lostAddress) external view returns (uint256) {
return claims[token][lostAddress].collateral;
}
function getCollateralType(IRecoverable token, address lostAddress) external view returns (IERC20) {
return claims[token][lostAddress].currencyUsed;
}
function getTimeStamp(IRecoverable token, address lostAddress) external view returns (uint256) {
return claims[token][lostAddress].timestamp;
}
/**
* Clears a claim after the key has been found again and assigns the collateral to the "lost" address.
* This is the price an adverse claimer pays for filing a false claim and makes it risky to do so.
*/
function clearClaimFromToken(address holder) external override {
clearClaim(IRecoverable(msg.sender), holder);
}
function clearClaimFromUser(IRecoverable token) external override {
clearClaim(token, msg.sender);
}
function clearClaim(IRecoverable token, address holder) private {
Claim memory claim = claims[token][holder];
if (claim.collateral > 0){
IERC20 currency = IERC20(claim.currencyUsed);
delete claims[token][holder];
currency.safeTransfer(holder, claim.collateral);
emit ClaimCleared(token, holder, claim.collateral);
}
IRecoverable(token).notifyClaimDeleted(holder);
}
/**
* After the claim period has passed, the claimant can call this function to send the
* tokens on the lost address as well as the collateral to himself.
*/
function recover(IRecoverable token, address lostAddress) external {
Claim memory claim = claims[token][lostAddress];
uint256 collateral = claim.collateral;
if (collateral == 0) {
revert RecoveryHub_ClaimNotFound(lostAddress);
}
address claimant = claim.claimant;
if (claimant != msg.sender) {
revert RecoveryHub_InvalidSender(msg.sender);
}
// rely on time stamp is ok, no exact time stamp needed
// solhint-disable-next-line not-rely-on-time
uint256 claimPeriodEnd = claim.timestamp + IRecoverable(token).claimPeriod();
if (claimPeriodEnd > block.timestamp) {
revert RecoveryHub_InClaimPeriod(claimPeriodEnd, block.timestamp);
}
delete claims[token][lostAddress];
emit ClaimResolved(token, lostAddress, claimant, collateral);
IRecoverable(token).notifyClaimDeleted(lostAddress);
IERC20 currency = IERC20(claim.currencyUsed);
currency.safeTransfer(claimant, collateral);
IRecoverable(token).recover(lostAddress, claimant);
}
/**
* The token contract can delete claims. It is the responsibility of the token contract to make sure
* only authorized parties can trigger such a call.
*/
function deleteClaim(address lostAddress) external override {
IRecoverable token = IRecoverable(msg.sender);
Claim memory claim = claims[token][lostAddress];
IERC20 currency = IERC20(claim.currencyUsed);
if (claim.collateral == 0) {
revert RecoveryHub_ClaimNotFound(lostAddress);
}
delete claims[token][lostAddress];
emit ClaimDeleted(token, lostAddress, claim.claimant, claim.collateral);
IRecoverable(token).notifyClaimDeleted(lostAddress);
currency.safeTransfer(claim.claimant, claim.collateral);
}
}/**
* SPDX-License-Identifier: MIT
*
* Copyright (c) 2016-2019 zOS Global Limited
*
*/
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see `ERC20Detailed`.
*/
interface IERC20 {
// Optional functions
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a `Transfer` event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through `transferFrom`. This is
* zero by default.
*
* This value changes when `approve` or `transferFrom` are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* > Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an `Approval` event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a `Transfer` event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to `approve`. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
// Copied from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/draft-IERC20Permit.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit is IERC20 {
/*//////////////////////////////////////////////////////////////
Custom errors
//////////////////////////////////////////////////////////////*/
/// Block timestamp must to be before deadline.
/// @param deadline The deadline of the permit.
/// @param blockTimestamp The timestamp of the execution block.
error Permit_DeadlineExpired(uint256 deadline, uint256 blockTimestamp);
/// Recovered address must be owner and not zero address.
/// @param signerAddress The recovered signer address.
error Permit_InvalidSigner(address signerAddress);
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../ERC20/IERC20.sol";
import "./IRecoveryHub.sol";
interface IRecoverable is IERC20{
/*//////////////////////////////////////////////////////////////
Custom errors
//////////////////////////////////////////////////////////////*/
/// The new custom claim collateral rate has to be always > 0.
error Recoverable_RateZero();
// returns the recovery hub
function recovery() external view returns (IRecoveryHub);
function claimPeriod() external view returns (uint256);
function notifyClaimMade(address target) external;
function notifyClaimDeleted(address target) external;
function getCollateralRate(IERC20 collateral) external view returns(uint256);
function recover(address oldAddress, address newAddress) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IRecoverable.sol";
import "../ERC20/IERC20.sol";
interface IRecoveryHub {
/*//////////////////////////////////////////////////////////////
Custom errors
//////////////////////////////////////////////////////////////*/
/// Recovery can be disabled per address.
/// @param lostAddress The address for which the recovery is disabled.
error RecoveryHub_RecoveryDisabled(address lostAddress);
/// No valid collateral type
/// @param collateralType The address of collateral type token
error RecoveryHub_BadCollateral(IERC20 collateralType);
/// No token to able to recover on the lost address
/// @param token The token address which is checked for recovery.
/// @param lostAddress The lost address.
error RecoveryHub_NothingToRecover(IERC20 token, address lostAddress);
/// The was already a claim for this token and address.
/// @param token The token address.
/// @param lostAddress The lost address.
error RecoveryHub_AlreadyClaimed(IERC20 token, address lostAddress);
/// Sender has to be claimant
/// @param sender The msg.sender of the call
error RecoveryHub_InvalidSender(address sender);
/// No claim for this address exists
/// @param lostAddress The checked address
error RecoveryHub_ClaimNotFound(address lostAddress);
/// Recover can only be called after the claim period
/// @param claimPeriodEnd The timestamp when the period ends
/// @param currentTimestamp The block timestamp of the call
error RecoveryHub_InClaimPeriod(uint256 claimPeriodEnd, uint256 currentTimestamp);
function setRecoverable(bool flag) external;
// deletes claim and transfers collateral back to claimer
function deleteClaim(address target) external;
// clears claim and transfers collateral to holder
function clearClaimFromToken(address holder) external;
function clearClaimFromUser(IRecoverable token) external;
}// SPDX-License-Identifier: MIT
// Copied from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol
// and modified it.
pragma solidity ^0.8.0;
library Address {
/// @param target Target address to call the function on.
error Address_NotTransferNorContract(address target);
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 weiValue) internal returns (bytes memory) {
if (data.length != 0 && !isContract(target)) {
revert Address_NotTransferNorContract(target);
}
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else if (returndata.length > 0) {
assembly{
revert (add (returndata, 0x20), mload (returndata))
}
} else {
revert("failed");
}
}
}// SPDX-License-Identifier: MIT
// coppied and adjusted from OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../ERC20/IERC20.sol";
import {IERC20Permit} from "../ERC20/IERC20Permit.sol";
import {Address} from "./Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
if (nonceAfter != nonceBefore + 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}{
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"Address_NotTransferNorContract","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"lostAddress","type":"address"}],"name":"RecoveryHub_AlreadyClaimed","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"collateralType","type":"address"}],"name":"RecoveryHub_BadCollateral","type":"error"},{"inputs":[{"internalType":"address","name":"lostAddress","type":"address"}],"name":"RecoveryHub_ClaimNotFound","type":"error"},{"inputs":[{"internalType":"uint256","name":"claimPeriodEnd","type":"uint256"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"}],"name":"RecoveryHub_InClaimPeriod","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"RecoveryHub_InvalidSender","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"lostAddress","type":"address"}],"name":"RecoveryHub_NothingToRecover","type":"error"},{"inputs":[{"internalType":"address","name":"lostAddress","type":"address"}],"name":"RecoveryHub_RecoveryDisabled","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IRecoverable","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"lostAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateral","type":"uint256"}],"name":"ClaimCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IRecoverable","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"lostAddress","type":"address"},{"indexed":true,"internalType":"address","name":"claimant","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateral","type":"uint256"}],"name":"ClaimDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IRecoverable","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"lostAddress","type":"address"},{"indexed":true,"internalType":"address","name":"claimant","type":"address"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"ClaimMade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IRecoverable","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"lostAddress","type":"address"},{"indexed":true,"internalType":"address","name":"claimant","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateral","type":"uint256"}],"name":"ClaimResolved","type":"event"},{"inputs":[{"internalType":"contract IRecoverable","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"claims","outputs":[{"internalType":"address","name":"claimant","type":"address"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"contract IERC20","name":"currencyUsed","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"}],"name":"clearClaimFromToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRecoverable","name":"token","type":"address"}],"name":"clearClaimFromUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRecoverable","name":"token","type":"address"},{"internalType":"contract IERC20","name":"collateralType","type":"address"},{"internalType":"address","name":"lostAddress","type":"address"}],"name":"declareLost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lostAddress","type":"address"}],"name":"deleteClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRecoverable","name":"token","type":"address"},{"internalType":"address","name":"lostAddress","type":"address"}],"name":"getClaimant","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IRecoverable","name":"token","type":"address"},{"internalType":"address","name":"lostAddress","type":"address"}],"name":"getCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IRecoverable","name":"token","type":"address"},{"internalType":"address","name":"lostAddress","type":"address"}],"name":"getCollateralType","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IRecoverable","name":"token","type":"address"},{"internalType":"address","name":"lostAddress","type":"address"}],"name":"getTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"isRecoverable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IRecoverable","name":"token","type":"address"},{"internalType":"address","name":"lostAddress","type":"address"}],"name":"recover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"recoveryDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setRecoverable","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052348015600f57600080fd5b50610fd68061001f6000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c806352226ef01161008c578063b40e80d111610066578063b40e80d114610263578063c1e5857314610286578063cc0720cc14610299578063e334860a146102e757600080fd5b806352226ef0146101e95780636427ed9714610223578063648bf7741461025057600080fd5b806306036025146100d457806323cd9a86146100e95780632851bbc91461010f57806332a7ae951461014c5780633f733c6b1461015f5780634d301a30146101d6575b600080fd5b6100e76100e2366004610e2f565b610320565b005b6100fc6100f7366004610e4c565b61032d565b6040519081526020015b60405180910390f35b61013c61011d366004610e2f565b6001600160a01b031660009081526001602052604090205460ff161590565b6040519015158152602001610106565b6100e761015a366004610e2f565b61035b565b6101a761016d366004610e4c565b600060208181529281526040808220909352908152208054600182015460028301546003909301546001600160a01b039283169391921684565b604080516001600160a01b03958616815260208101949094528301919091529091166060820152608001610106565b6100e76101e4366004610e2f565b6104eb565b6100fc6101f7366004610e4c565b6001600160a01b0391821660009081526020818152604080832093909416825291909152206001015490565b6100e7610231366004610e93565b336000908152600160205260409020805460ff19169115919091179055565b6100e761025e366004610e4c565b6104f5565b61013c610271366004610e2f565b60016020526000908152604090205460ff1681565b6100e7610294366004610eb0565b6107a9565b6102cf6102a7366004610e4c565b6001600160a01b03918216600090815260208181526040808320938516835292905220541690565b6040516001600160a01b039091168152602001610106565b6102cf6102f5366004610e4c565b6001600160a01b03918216600090815260208181526040808320938516835292905220600301541690565b61032a8133610a9c565b50565b6001600160a01b03808316600090815260208181526040808320938516835292905220600201545b92915050565b336000818152602081815260408083206001600160a01b038681168552908352818420825160808101845281548316815260018201549481018590526002820154938101939093526003015416606082018190529092909190036103e25760405163bca13b6b60e01b81526001600160a01b03851660048201526024015b60405180910390fd5b6001600160a01b0383811660008181526020818152604080832089861680855290835281842080546001600160a01b0319908116825560018201869055600282019590955560030180549094169093558651878301519151918252909416939192917fe353e089146c0574fa0001d9aa56c67a4eee067d8730543ae0ee937a30d679f3910160405180910390a460405163396e093b60e21b81526001600160a01b03858116600483015284169063e5b824ec90602401600060405180830381600087803b1580156104b257600080fd5b505af11580156104c6573d6000803e3d6000fd5b5050835160208501516104e593506001600160a01b0385169250610c0e565b50505050565b61032a3382610a9c565b6001600160a01b038083166000908152602081815260408083208585168452825280832081516080810183528154861681526001820154938101849052600282015492810192909252600301549093166060840152908190036105765760405163bca13b6b60e01b81526001600160a01b03841660048201526024016103d9565b81516001600160a01b03811633146105a35760405163a755367960e01b81523360048201526024016103d9565b6000856001600160a01b0316637dc2cd986040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106079190610efb565b84604001516106169190610f2a565b9050428111156106425760405163065d672f60e41b8152600481018290524260248201526044016103d9565b6001600160a01b038681166000818152602081815260408083208a861680855290835281842080546001600160a01b03199081168255600182018690556002820195909555600301805490941690935551878152938616939192917f03746d4086c981172ed0a960601bec02cfe0a2ecbe1b1b4e328752bbf5d0c255910160405180910390a460405163396e093b60e21b81526001600160a01b03868116600483015287169063e5b824ec90602401600060405180830381600087803b15801561070b57600080fd5b505af115801561071f573d6000803e3d6000fd5b50505050606084015161073c6001600160a01b0382168486610c0e565b604051631922fddd60e21b81526001600160a01b038781166004830152848116602483015288169063648bf774906044015b600060405180830381600087803b15801561078857600080fd5b505af115801561079c573d6000803e3d6000fd5b5050505050505050505050565b6001600160a01b03811660009081526001602052604090205460ff16156107f15760405160016234012160e11b031981526001600160a01b03821660048201526024016103d9565b6040516377e071ad60e01b81526001600160a01b038381166004830152600091908516906377e071ad90602401602060405180830381865afa15801561083b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085f9190610efb565b90508060000361088d5760405163df8c6ee360e01b81526001600160a01b03841660048201526024016103d9565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908616906370a0823190602401602060405180830381865afa1580156108d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108fb9190610efb565b90508060000361093157604051630b31b77b60e01b81526001600160a01b038087166004830152841660248201526044016103d9565b600061093d8383610f3d565b6001600160a01b038088166000908152602081815260408083209389168352929052206001015490915085901561099a57604051636dee9c8560e01b81526001600160a01b038089166004830152861660248201526044016103d9565b60408051608081018252338082526020808301868152428486019081526001600160a01b038c8116606087019081528e821660008181528087528981208f85168083529752899020975188549084166001600160a01b03199182161789559451600189015592516002880155516003909601805496909116959092169490941790559251909291907f6bfd50306449d9d6c51593433950fc186e4ab99a885ed357a34549bfd7a2668f90610a519088815260200190565b60405180910390a4610a6e6001600160a01b038216333085610c72565b6040516330605cb160e21b81526001600160a01b03868116600483015288169063c18172c49060240161076e565b6001600160a01b038083166000908152602081815260408083208585168452825291829020825160808101845281548516815260018201549281018390526002820154938101939093526003015490921660608201529015610bae5760608101516001600160a01b0380851660009081526020818152604080832087851684528252822080546001600160a01b031990811682556001820184905560028201939093556003018054909216909155830151610b5b918316908590610c0e565b826001600160a01b0316846001600160a01b03167febe2b7544a1a711c29034fc19c1b200f13cf4ec175198e0f857735ed4f5f9bd18460200151604051610ba491815260200190565b60405180910390a3505b60405163396e093b60e21b81526001600160a01b03838116600483015284169063e5b824ec90602401600060405180830381600087803b158015610bf157600080fd5b505af1158015610c05573d6000803e3d6000fd5b50505050505050565b6040516001600160a01b03838116602483015260448201839052610c6d91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610cab565b505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526104e59186918216906323b872dd90608401610c3b565b6000610cc06001600160a01b03841683610d0e565b90508051600014158015610ce5575080806020019051810190610ce39190610f54565b155b15610c6d57604051635274afe760e01b81526001600160a01b03841660048201526024016103d9565b6060610d1c83836000610d23565b9392505050565b60608251600014158015610d3f57506001600160a01b0384163b155b15610d6857604051639eb1341360e01b81526001600160a01b03851660048201526024016103d9565b600080856001600160a01b03168486604051610d849190610f71565b60006040518083038185875af1925050503d8060008114610dc1576040519150601f19603f3d011682016040523d82523d6000602084013e610dc6565b606091505b50915091508115610dda579150610d1c9050565b805115610de957805160208201fd5b60405162461bcd60e51b815260206004820152600660248201526519985a5b195960d21b60448201526064016103d9565b6001600160a01b038116811461032a57600080fd5b600060208284031215610e4157600080fd5b8135610d1c81610e1a565b60008060408385031215610e5f57600080fd5b8235610e6a81610e1a565b91506020830135610e7a81610e1a565b809150509250929050565b801515811461032a57600080fd5b600060208284031215610ea557600080fd5b8135610d1c81610e85565b600080600060608486031215610ec557600080fd5b8335610ed081610e1a565b92506020840135610ee081610e1a565b91506040840135610ef081610e1a565b809150509250925092565b600060208284031215610f0d57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561035557610355610f14565b808202811582820484141761035557610355610f14565b600060208284031215610f6657600080fd5b8151610d1c81610e85565b6000825160005b81811015610f925760208186018101518583015201610f78565b50600092019182525091905056fea26469706673582212201e5663ae574cd2b9f29c7f45f02f888b5e5359181ee0275ee0db63fe25f5516664736f6c63430008190033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c806352226ef01161008c578063b40e80d111610066578063b40e80d114610263578063c1e5857314610286578063cc0720cc14610299578063e334860a146102e757600080fd5b806352226ef0146101e95780636427ed9714610223578063648bf7741461025057600080fd5b806306036025146100d457806323cd9a86146100e95780632851bbc91461010f57806332a7ae951461014c5780633f733c6b1461015f5780634d301a30146101d6575b600080fd5b6100e76100e2366004610e2f565b610320565b005b6100fc6100f7366004610e4c565b61032d565b6040519081526020015b60405180910390f35b61013c61011d366004610e2f565b6001600160a01b031660009081526001602052604090205460ff161590565b6040519015158152602001610106565b6100e761015a366004610e2f565b61035b565b6101a761016d366004610e4c565b600060208181529281526040808220909352908152208054600182015460028301546003909301546001600160a01b039283169391921684565b604080516001600160a01b03958616815260208101949094528301919091529091166060820152608001610106565b6100e76101e4366004610e2f565b6104eb565b6100fc6101f7366004610e4c565b6001600160a01b0391821660009081526020818152604080832093909416825291909152206001015490565b6100e7610231366004610e93565b336000908152600160205260409020805460ff19169115919091179055565b6100e761025e366004610e4c565b6104f5565b61013c610271366004610e2f565b60016020526000908152604090205460ff1681565b6100e7610294366004610eb0565b6107a9565b6102cf6102a7366004610e4c565b6001600160a01b03918216600090815260208181526040808320938516835292905220541690565b6040516001600160a01b039091168152602001610106565b6102cf6102f5366004610e4c565b6001600160a01b03918216600090815260208181526040808320938516835292905220600301541690565b61032a8133610a9c565b50565b6001600160a01b03808316600090815260208181526040808320938516835292905220600201545b92915050565b336000818152602081815260408083206001600160a01b038681168552908352818420825160808101845281548316815260018201549481018590526002820154938101939093526003015416606082018190529092909190036103e25760405163bca13b6b60e01b81526001600160a01b03851660048201526024015b60405180910390fd5b6001600160a01b0383811660008181526020818152604080832089861680855290835281842080546001600160a01b0319908116825560018201869055600282019590955560030180549094169093558651878301519151918252909416939192917fe353e089146c0574fa0001d9aa56c67a4eee067d8730543ae0ee937a30d679f3910160405180910390a460405163396e093b60e21b81526001600160a01b03858116600483015284169063e5b824ec90602401600060405180830381600087803b1580156104b257600080fd5b505af11580156104c6573d6000803e3d6000fd5b5050835160208501516104e593506001600160a01b0385169250610c0e565b50505050565b61032a3382610a9c565b6001600160a01b038083166000908152602081815260408083208585168452825280832081516080810183528154861681526001820154938101849052600282015492810192909252600301549093166060840152908190036105765760405163bca13b6b60e01b81526001600160a01b03841660048201526024016103d9565b81516001600160a01b03811633146105a35760405163a755367960e01b81523360048201526024016103d9565b6000856001600160a01b0316637dc2cd986040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106079190610efb565b84604001516106169190610f2a565b9050428111156106425760405163065d672f60e41b8152600481018290524260248201526044016103d9565b6001600160a01b038681166000818152602081815260408083208a861680855290835281842080546001600160a01b03199081168255600182018690556002820195909555600301805490941690935551878152938616939192917f03746d4086c981172ed0a960601bec02cfe0a2ecbe1b1b4e328752bbf5d0c255910160405180910390a460405163396e093b60e21b81526001600160a01b03868116600483015287169063e5b824ec90602401600060405180830381600087803b15801561070b57600080fd5b505af115801561071f573d6000803e3d6000fd5b50505050606084015161073c6001600160a01b0382168486610c0e565b604051631922fddd60e21b81526001600160a01b038781166004830152848116602483015288169063648bf774906044015b600060405180830381600087803b15801561078857600080fd5b505af115801561079c573d6000803e3d6000fd5b5050505050505050505050565b6001600160a01b03811660009081526001602052604090205460ff16156107f15760405160016234012160e11b031981526001600160a01b03821660048201526024016103d9565b6040516377e071ad60e01b81526001600160a01b038381166004830152600091908516906377e071ad90602401602060405180830381865afa15801561083b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085f9190610efb565b90508060000361088d5760405163df8c6ee360e01b81526001600160a01b03841660048201526024016103d9565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908616906370a0823190602401602060405180830381865afa1580156108d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108fb9190610efb565b90508060000361093157604051630b31b77b60e01b81526001600160a01b038087166004830152841660248201526044016103d9565b600061093d8383610f3d565b6001600160a01b038088166000908152602081815260408083209389168352929052206001015490915085901561099a57604051636dee9c8560e01b81526001600160a01b038089166004830152861660248201526044016103d9565b60408051608081018252338082526020808301868152428486019081526001600160a01b038c8116606087019081528e821660008181528087528981208f85168083529752899020975188549084166001600160a01b03199182161789559451600189015592516002880155516003909601805496909116959092169490941790559251909291907f6bfd50306449d9d6c51593433950fc186e4ab99a885ed357a34549bfd7a2668f90610a519088815260200190565b60405180910390a4610a6e6001600160a01b038216333085610c72565b6040516330605cb160e21b81526001600160a01b03868116600483015288169063c18172c49060240161076e565b6001600160a01b038083166000908152602081815260408083208585168452825291829020825160808101845281548516815260018201549281018390526002820154938101939093526003015490921660608201529015610bae5760608101516001600160a01b0380851660009081526020818152604080832087851684528252822080546001600160a01b031990811682556001820184905560028201939093556003018054909216909155830151610b5b918316908590610c0e565b826001600160a01b0316846001600160a01b03167febe2b7544a1a711c29034fc19c1b200f13cf4ec175198e0f857735ed4f5f9bd18460200151604051610ba491815260200190565b60405180910390a3505b60405163396e093b60e21b81526001600160a01b03838116600483015284169063e5b824ec90602401600060405180830381600087803b158015610bf157600080fd5b505af1158015610c05573d6000803e3d6000fd5b50505050505050565b6040516001600160a01b03838116602483015260448201839052610c6d91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610cab565b505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526104e59186918216906323b872dd90608401610c3b565b6000610cc06001600160a01b03841683610d0e565b90508051600014158015610ce5575080806020019051810190610ce39190610f54565b155b15610c6d57604051635274afe760e01b81526001600160a01b03841660048201526024016103d9565b6060610d1c83836000610d23565b9392505050565b60608251600014158015610d3f57506001600160a01b0384163b155b15610d6857604051639eb1341360e01b81526001600160a01b03851660048201526024016103d9565b600080856001600160a01b03168486604051610d849190610f71565b60006040518083038185875af1925050503d8060008114610dc1576040519150601f19603f3d011682016040523d82523d6000602084013e610dc6565b606091505b50915091508115610dda579150610d1c9050565b805115610de957805160208201fd5b60405162461bcd60e51b815260206004820152600660248201526519985a5b195960d21b60448201526064016103d9565b6001600160a01b038116811461032a57600080fd5b600060208284031215610e4157600080fd5b8135610d1c81610e1a565b60008060408385031215610e5f57600080fd5b8235610e6a81610e1a565b91506020830135610e7a81610e1a565b809150509250929050565b801515811461032a57600080fd5b600060208284031215610ea557600080fd5b8135610d1c81610e85565b600080600060608486031215610ec557600080fd5b8335610ed081610e1a565b92506020840135610ee081610e1a565b91506040840135610ef081610e1a565b809150509250925092565b600060208284031215610f0d57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561035557610355610f14565b808202811582820484141761035557610355610f14565b600060208284031215610f6657600080fd5b8151610d1c81610e85565b6000825160005b81811015610f925760208186018101518583015201610f78565b50600092019182525091905056fea26469706673582212201e5663ae574cd2b9f29c7f45f02f888b5e5359181ee0275ee0db63fe25f5516664736f6c63430008190033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$12.80
Net Worth in POL
Token Allocations
ZCHF
100.00%
Multichain Portfolio | 32 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| POL | 100.00% | $1.28 | 10 | $12.8 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.