ETH Token Recover
TokenRecover allows to recover any ERC-20 or NFT (ERC-721) token sent into the contract and sends them to a receiver.
There are lots of tokens lost forever into Smart Contracts (see OMG token balances). Each Ethereum contract, as well as any EVM compatible contract, is a potential token trap for ERC-20 or ERC-721 tokens. They can't be recovered, so it means money losses for end users.
By using TokenRecover, any smart contract can offer users a robust solution for reclaiming mistakenly or erroneously sent tokens, enhancing the overall user experience and confidence in the decentralized ecosystem.
Install
npm install eth-token-recover
Recovers
The recover
contracts define internal methods that can be used in derived contracts.
RecoverERC20
Allows to recover any ERC-20 token sent into the contract and sends them to a receiver.
WARNING
It allows everyone to recover tokens. Access controls MUST be defined in derived contracts.
pragma solidity ^0.8.20;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
abstract contract RecoverERC20 {
function _recoverERC20(address tokenAddress, address tokenReceiver, uint256 tokenAmount) internal virtual {
IERC20(tokenAddress).transfer(tokenReceiver, tokenAmount);
}
}
RecoverERC721
Allows to recover any ERC-721 token sent into the contract and sends them to a receiver.
WARNING
It allows everyone to recover tokens. Access controls MUST be defined in derived contracts.
pragma solidity ^0.8.20;
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
abstract contract RecoverERC721 {
function _recoverERC721(address tokenAddress, address tokenReceiver, uint256 tokenId, bytes memory data) internal virtual {
IERC721(tokenAddress).safeTransferFrom(address(this), tokenReceiver, tokenId, data);
}
}
Usage
The below contracts define high level code that can be inherited as is or extended to cover desired behaviors.
ERC20Recover
Allows the contract owner to recover any ERC-20 token sent into the contract and sends them to a receiver.
IMPORTANT
This contract is Ownable
and restricts access to recover method to owner only.
Use ERC20Recover
pragma solidity ^0.8.20;
import {ERC20Recover} from "eth-token-recover/contracts/ERC20Recover.sol";
contract MyContract is ERC20Recover {
constructor(address initialOwner) ERC20Recover(initialOwner) {
// your stuff
}
// your stuff
}
ERC721Recover
Allows the contract owner to recover any ERC-721 token sent into the contract and sends them to a receiver.
IMPORTANT
This contract is Ownable
and restricts access to recover method to owner only.
Use ERC721Recover
pragma solidity ^0.8.20;
import {ERC721Recover} from "eth-token-recover/contracts/ERC721Recover.sol";
contract MyContract is ERC721Recover {
constructor(address initialOwner) ERC721Recover(initialOwner) {
// your stuff
}
// your stuff
}
TokenRecover
Allows the contract owner to recover any ERC-20 or ERC-721 token sent into the contract and sends them to a receiver.
IMPORTANT
This contract is Ownable
and restricts access to recover methods to owner only.
Use TokenRecover
pragma solidity ^0.8.20;
import {TokenRecover} from "eth-token-recover/contracts/TokenRecover.sol";
contract MyContract is TokenRecover {
constructor(address initialOwner) TokenRecover(initialOwner) {
// your stuff
}
// your stuff
}
Examples
Contracts can be extended to add custom logic (e.g. to add custom roles or rules).
Add rules to high level
pragma solidity ^0.8.20;
import {TokenRecover} from "eth-token-recover/contracts/TokenRecover.sol";
import {MyDefinedRules} from "./MyDefinedRules.sol";
contract MyContract is TokenRecover, MyDefinedRules {
constructor(address initialOwner) TokenRecover(initialOwner) {
// your stuff
}
// your stuff
function recoverERC20(address tokenAddress, address tokenReceiver, uint256 tokenAmount) public virtual override alsoMyRule {
// your stuff
super.recoverERC20(tokenAddress, tokenReceiver, tokenAmount);
// your stuff
}
}
Add rules to low level
pragma solidity ^0.8.20;
import {RecoverERC20} from "eth-token-recover/contracts/recover/RecoverERC20.sol";
import {MyDefinedRules} from "./MyDefinedRules.sol";
contract MyContract is RecoverERC20, MyDefinedRules {
// your stuff
function myRecoverERC20(address tokenAddress, address tokenReceiver, uint256 tokenAmount) public virtual onlyMyRule {
// your stuff
_recoverERC20(tokenAddress, tokenReceiver, tokenAmount);
// your stuff
}
}
Migrating from 4.x
WARNING
The TokenRecover
constructor now requires an initialOwner
parameter, making the ownership initialization explicit.
A contract inheriting from TokenRecover
needs to be updated in the following way.
pragma solidity ^0.8.20;
import {TokenRecover} from "eth-token-recover/contracts/TokenRecover.sol";
contract MyContract is TokenRecover {
+ constructor(address initialOwner) TokenRecover(initialOwner) {
+ // your stuff
+ }
// your stuff
}
WARNING
The v4.x (and earlier) TokenRecover::recoverERC20
method has been updated to accept the tokenReceiver
address, the address that will receive the recovered token.
-function recoverERC20(address tokenAddress, uint256 tokenAmount) public virtual onlyOwner
+function recoverERC20(address tokenAddress, address tokenReceiver, uint256 tokenAmount) public virtual onlyOwner
Check the Backwards Compatibility section for additional details.
Backwards Compatibility
A backward compatible (legacy) version is available in the legacy
folder.
TokenRecoverLegacy
contract will:
- implicitly set the deployer as contract owner
- send recovered tokens to owner instead of providing an explicit receiver
To use TokenRecoverLegacy
, a contract inheriting from TokenRecover
needs to be updated in the following way
pragma solidity ^0.8.20;
-import {TokenRecover} from "eth-token-recover/contracts/TokenRecover.sol";
+import {TokenRecoverLegacy} from "eth-token-recover/contracts/legacy/TokenRecoverLegacy.sol";
-contract MyContract is TokenRecover {
+contract MyContract is TokenRecoverLegacy {
// your stuff
}
CAUTION
TokenRecoverLegacy
is a legacy version of TokenRecover
that works as v4.x and earlier and MAY be removed in future releases.
We highly recommend to keep the code updated to use newer versions of the recover.
Documentation
Code Analysis
Development
Install dependencies
npm install
Compile
npm run compile
Test
npm test
Code Coverage
npm run coverage
Linter
Check Solidity files
npm run lint:sol
Check JS/TS files
npm run lint:js
Fix JS and Solidity files
npm run lint:fix
License
Code released under the MIT License.