Skip to content

Commit

Permalink
feat: rebase contracts and support ERC721 (#19)
Browse files Browse the repository at this point in the history
* feat: moved erc20 recover to a dedicated contract
* feat: add NFT recover (ERC721)
* feat: remove examples
* feat: update solc to 0.8.22
* docs: update documentation
  • Loading branch information
vittominacori authored Oct 26, 2023
1 parent bfad07f commit 53fd6d6
Show file tree
Hide file tree
Showing 58 changed files with 3,878 additions and 193 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# vuepress deploy
GIT_DEPLOY_DIR=docs/.vuepress/dist
GIT_DEPLOY_DIR=pages/.vuepress/dist
GIT_DEPLOY_BRANCH=gh-pages
GIT_DEPLOY_REPO=origin
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,13 @@ jobs:
codespell:
name: Codespell
runs-on: ubuntu-latest
env:
FORCE_COLOR: 1
steps:
- uses: actions/checkout@v4
- name: Run CodeSpell
uses: codespell-project/actions-codespell@v2.0
with:
check_hidden: true
check_filenames: true
skip: package-lock.json
skip: .git,package-lock.json
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,5 @@ contracts-exposed
.idea

# vuepress
docs/.vuepress/dist
docs/.vuepress/.env.json
pages/.vuepress/dist
pages/.vuepress/.env.json
185 changes: 159 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,98 +5,231 @@
[![Coverage Status](https://codecov.io/gh/vittominacori/eth-token-recover/graph/badge.svg)](https://codecov.io/gh/vittominacori/eth-token-recover)
[![MIT licensed](https://img.shields.io/github/license/vittominacori/eth-token-recover.svg)](https://github.com/vittominacori/eth-token-recover/blob/master/LICENSE)

TokenRecover allows the contract owner to recover any ERC20 token sent into the contract for error.
TokenRecover allows to recover any ERC20 or ERC721 token sent into the contract and send them to a receiver.

## Motivation

There are lots of tokens lost forever into Smart Contracts (see [OMG](https://etherscan.io/address/0xd26114cd6ee289accf82350c8d8487fedb8a0c07) token balances).
Each Ethereum contract is a potential token trap for ERC20 tokens. They can't be recovered, so it means money losses for end users.
Each Ethereum contract is a potential token trap for ERC20 or ERC721 tokens. They can't be recovered, so it means money losses for end users.

## Install

```bash
npm install eth-token-recover
```

## Recovers

The `recover` contracts define internal methods that can be used in derived contracts.

### RecoverERC20

[RecoverERC20.sol](https://github.com/vittominacori/eth-token-recover/blob/master/contracts/recover/RecoverERC20.sol)

Allows to recover any ERC20 token sent into the contract and send them to a receiver.

::: warning WARNING
It allows everyone to recover tokens. Access controls MUST be defined in derived contracts.
:::

```solidity
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

[RecoverERC721.sol](https://github.com/vittominacori/eth-token-recover/blob/master/contracts/recover/RecoverERC721.sol)

Allows to recover any ERC721 token sent into the contract and send them to a receiver.

::: warning WARNING
It allows everyone to recover tokens. Access controls MUST be defined in derived contracts.
:::

```solidity
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

### Provide your defined owner
The below contracts define high level code that can be inherited as is or extended to cover desired behaviors.

### ERC20Recover

[ERC20Recover.sol](https://github.com/vittominacori/eth-token-recover/blob/master/contracts/ERC20Recover.sol)

Allows the contract owner to recover any ERC20 token sent into the contract and send them to a receiver.

::: tip NOTE
This contract is `Ownable` and restricts access to recover method to owner only.
:::

#### Use ERC20Recover

```solidity
pragma solidity ^0.8.20;
import {TokenRecover} from "eth-token-recover/contracts/TokenRecover.sol";
import {ERC20Recover} from "eth-token-recover/contracts/ERC20Recover.sol";
contract MyContract is TokenRecover {
contract MyContract is ERC20Recover {
constructor(address originalOwner) ERC20Recover(originalOwner) {
// your stuff
}
// your stuff
}
```

constructor(address originalOwner) TokenRecover(originalOwner) {
### ERC721Recover

[ERC721Recover.sol](https://github.com/vittominacori/eth-token-recover/blob/master/contracts/ERC721Recover.sol)

Allows the contract owner to recover any ERC721 token sent into the contract and send them to a receiver.

::: tip NOTE
This contract is `Ownable` and restricts access to recover method to owner only.
:::

#### Use ERC721Recover

```solidity
pragma solidity ^0.8.20;
import {ERC721Recover} from "eth-token-recover/contracts/ERC721Recover.sol";
contract MyContract is ERC721Recover {
constructor(address originalOwner) ERC721Recover(originalOwner) {
// your stuff
}
// your stuff
}
```

### Use deployer as owner
### TokenRecover

[TokenRecover.sol](https://github.com/vittominacori/eth-token-recover/blob/master/contracts/TokenRecover.sol)

Allows the contract owner to recover any ERC20 or ERC721 token sent into the contract and send them to a receiver.

::: tip NOTE
This contract is `Ownable` and restricts access to recover methods to owner only.
:::

#### Use TokenRecover

```solidity
pragma solidity ^0.8.20;
import {TokenRecover} from "eth-token-recover/contracts/TokenRecover.sol";
contract MyContract is TokenRecover {
constructor() TokenRecover(_msgSender()) {
constructor(address originalOwner) TokenRecover(originalOwner) {
// your stuff
}
// your stuff
}
```

## Code
## Examples

This repo contains:
You can extend the code to add your stuff (e.g. to add custom roles or rules).

* [TokenRecover.sol](https://github.com/vittominacori/eth-token-recover/blob/master/contracts/TokenRecover.sol)

Contract has a `recoverERC20` function that transfers a `tokenAmount` amount of `tokenAddress` token to the contract owner.
### Add rules to high level code

```solidity
function recoverERC20(address tokenAddress, uint256 tokenAmount) public virtual onlyOwner;
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 originalOwner) TokenRecover(originalOwner) {
// 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
}
}
```

Note: only owner can call the `recoverERC20` function so be careful when use on contracts generated from other contracts.
### Add rules to low level code

## Development
```solidity
pragma solidity ^0.8.20;
### Install dependencies
import {RecoverERC20} from "eth-token-recover/contracts/recover/RecoverERC20.sol";
import {MyDefinedRules} from "./MyDefinedRules.sol";
```bash
npm install
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
}
}
```

### Usage
## Documentation

* [Documentation](https://github.com/vittominacori/eth-token-recover/blob/master/docs/index.md)

## Code Analysis

Open the console
* [Control Flow](https://github.com/vittominacori/eth-token-recover/tree/master/analysis/control-flow)
* [Description Table](https://github.com/vittominacori/eth-token-recover/tree/master/analysis/description-table)
* [Inheritance Tree](https://github.com/vittominacori/eth-token-recover/tree/master/analysis/inheritance-tree)
* [UML](https://github.com/vittominacori/eth-token-recover/tree/master/analysis/uml)

## Development

### Install dependencies

```bash
npm run console
npm install
```

#### Compile
### Compile

```bash
npm run compile
```

#### Test
### Test

```bash
npm test
```

#### Code Coverage
### Code Coverage

```bash
npm run coverage
Expand Down
Empty file added analysis/.gitkeep
Empty file.
Empty file added analysis/control-flow/.gitkeep
Empty file.
Binary file added analysis/control-flow/ERC20Recover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added analysis/control-flow/ERC721Recover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added analysis/control-flow/TokenRecover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
51 changes: 51 additions & 0 deletions analysis/description-table/ERC20Recover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
## Sūrya's Description Report

### Files Description Table


| File Name | SHA-1 Hash |
|-------------|--------------|
| dist/ERC20Recover.dist.sol | [object Promise] |


### Contracts Description Table


| Contract | Type | Bases | | |
|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|
|| **Function Name** | **Visibility** | **Mutability** | **Modifiers** |
||||||
| **Context** | Implementation | |||
|| _msgSender | Internal 🔒 | | |
|| _msgData | Internal 🔒 | | |
||||||
| **Ownable** | Implementation | Context |||
|| <Constructor> | Public ❗️ | 🛑 |NO❗️ |
|| owner | Public ❗️ | |NO❗️ |
|| _checkOwner | Internal 🔒 | | |
|| renounceOwnership | Public ❗️ | 🛑 | onlyOwner |
|| transferOwnership | Public ❗️ | 🛑 | onlyOwner |
|| _transferOwnership | Internal 🔒 | 🛑 | |
||||||
| **IERC20** | Interface | |||
|| totalSupply | External ❗️ | |NO❗️ |
|| balanceOf | External ❗️ | |NO❗️ |
|| transfer | External ❗️ | 🛑 |NO❗️ |
|| allowance | External ❗️ | |NO❗️ |
|| approve | External ❗️ | 🛑 |NO❗️ |
|| transferFrom | External ❗️ | 🛑 |NO❗️ |
||||||
| **RecoverERC20** | Implementation | |||
|| _recoverERC20 | Internal 🔒 | 🛑 | |
||||||
| **ERC20Recover** | Implementation | Ownable, RecoverERC20 |||
|| <Constructor> | Public ❗️ | 🛑 | Ownable |
|| recoverERC20 | Public ❗️ | 🛑 | onlyOwner |


### Legend

| Symbol | Meaning |
|:--------:|-----------|
| 🛑 | Function can modify state |
| 💵 | Function is payable |
57 changes: 57 additions & 0 deletions analysis/description-table/ERC721Recover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
## Sūrya's Description Report

### Files Description Table


| File Name | SHA-1 Hash |
|-------------|--------------|
| dist/ERC721Recover.dist.sol | [object Promise] |


### Contracts Description Table


| Contract | Type | Bases | | |
|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|
|| **Function Name** | **Visibility** | **Mutability** | **Modifiers** |
||||||
| **Context** | Implementation | |||
|| _msgSender | Internal 🔒 | | |
|| _msgData | Internal 🔒 | | |
||||||
| **Ownable** | Implementation | Context |||
|| <Constructor> | Public ❗️ | 🛑 |NO❗️ |
|| owner | Public ❗️ | |NO❗️ |
|| _checkOwner | Internal 🔒 | | |
|| renounceOwnership | Public ❗️ | 🛑 | onlyOwner |
|| transferOwnership | Public ❗️ | 🛑 | onlyOwner |
|| _transferOwnership | Internal 🔒 | 🛑 | |
||||||
| **IERC165** | Interface | |||
|| supportsInterface | External ❗️ | |NO❗️ |
||||||
| **IERC721** | Interface | IERC165 |||
|| balanceOf | External ❗️ | |NO❗️ |
|| ownerOf | External ❗️ | |NO❗️ |
|| safeTransferFrom | External ❗️ | 🛑 |NO❗️ |
|| safeTransferFrom | External ❗️ | 🛑 |NO❗️ |
|| transferFrom | External ❗️ | 🛑 |NO❗️ |
|| approve | External ❗️ | 🛑 |NO❗️ |
|| setApprovalForAll | External ❗️ | 🛑 |NO❗️ |
|| getApproved | External ❗️ | |NO❗️ |
|| isApprovedForAll | External ❗️ | |NO❗️ |
||||||
| **RecoverERC721** | Implementation | |||
|| _recoverERC721 | Internal 🔒 | 🛑 | |
||||||
| **ERC721Recover** | Implementation | Ownable, RecoverERC721 |||
|| <Constructor> | Public ❗️ | 🛑 | Ownable |
|| recoverERC721 | Public ❗️ | 🛑 | onlyOwner |


### Legend

| Symbol | Meaning |
|:--------:|-----------|
| 🛑 | Function can modify state |
| 💵 | Function is payable |
Loading

0 comments on commit 53fd6d6

Please sign in to comment.