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.
npm install eth-token-recover
The recover
contracts define internal methods that can be used in derived contracts.
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);
}
}
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);
}
}
The below contracts define high level code that can be inherited as is or extended to cover desired behaviors.
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.
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
}
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.
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
}
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.
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
}
Contracts can be extended to add custom logic (e.g. to add custom roles or rules).
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
}
}
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
}
}
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.
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.
npm install
npm run compile
npm test
npm run coverage
Check Solidity files
npm run lint:sol
Check JS/TS files
npm run lint:js
Fix JS and Solidity files
npm run lint:fix
Code released under the MIT License.