├── .gitattributes
├── .github
└── workflows
│ ├── ci.yml
│ └── slither.yml
├── .gitignore
├── .prettierrc.json
├── LICENSE
├── README.md
├── addresses.json
├── contracts
├── ERC677.sol
├── ERC677TransferReceiverTest.sol
├── IERC677.sol
├── IERC677TransferReceiver.sol
└── Migrations.sol
├── datagen.js
├── migrations
├── 1_initial_migration.js
└── 2_erc677.js
├── package-lock.json
├── package.json
├── slither.config.json
├── test
└── erc677.test.js
└── truffle-config.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.sol linguist-language=Solidity
2 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | test:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 | - name: Use Node.js 10.x
17 | uses: actions/setup-node@v1
18 | with:
19 | node-version: 10.x
20 | - run: npm i
21 | - run: npm test
22 | - run: npm run coverage
23 | - run: npm run lint
24 | - name: Coveralls
25 | uses: coverallsapp/github-action@master
26 | with:
27 | github-token: ${{ secrets.GITHUB_TOKEN }}
28 |
--------------------------------------------------------------------------------
/.github/workflows/slither.yml:
--------------------------------------------------------------------------------
1 | name: slither scan
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | scan:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - name: Checkout
16 | uses: actions/checkout@v2
17 | - name: Setup Node
18 | uses: actions/setup-node@v1
19 | - run: npm i
20 | - name: Slither Static Analysis
21 | uses: luisfontes19/slither-static-analysis-action@v0.3.2
22 | with:
23 | slither-version: '0.6.13'
24 | run-npm-install: false
25 | high-threshold: 1
26 | medium-threshold: 1
27 | low-threshold: 3
28 | optimization-threshold: 5
29 | informative-threshold: 10
30 | projectPath: "."
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | build/
3 | ERC677Data.json
4 | types/
5 | coverage
6 | coverage.json
7 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 2,
3 | "bracketSpacing": true,
4 | "printWidth": 140
5 | }
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 IOV Studio LLP
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | @rsksmart/erc677
5 |
6 | Simple implementation of ERC-677 token contract, compatible with RIF Token.
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | > This package is only to **use for testing purposes**
27 |
28 | ## Install
29 |
30 | ```
31 | npm i @rsksmart/erc677
32 | ```
33 |
34 | ## Usage
35 |
36 | ```js
37 | const ERC677 = artifacts.require('@rsksmart/erc677');
38 |
39 | contract('My contract tests', async accounts => {
40 | let erc677;
41 |
42 | beforeEach(async () => {
43 | erc677 = await ERC677.new(
44 | accounts[0],
45 | web3.utils.toBN('1000000000000000000000'),
46 | 'RIFOS',
47 | 'RIF',
48 | web3.utils.toBN('18'),
49 | );
50 | });
51 | });
52 | ```
53 |
54 | ## JS
55 |
56 | ```js
57 | const Web3 = require('web3');
58 | const ERC677Data = require('@rsksmart/erc677/ERC677Data.json');
59 | const web3 = new Web3('https://public-node.rsk.co')
60 | const ERC677 = new web3.eth.Contract(ERC677Data.abi, ERC677Data.address.rskMainnet);
61 | ```
62 |
63 | ## Types
64 |
65 | There are TypeScript typing definitions of the contracts published together with the original contracts.
66 | Supported contract's libraries are:
67 |
68 | * `web3` version 1.* - `web3-v1-contracts`
69 | * `web3` version 2.* - `web3-v2-contracts`
70 | * `truffle` - `truffle-contracts`
71 | * `ethers` - `ethers-contracts`
72 |
73 | You can use them as follow:
74 |
75 | ```typescript
76 | import Web3 from 'web3'
77 | import ERC677 from '@rsksmart/erc677/types/web3-v1-contracts/ERC677Data.d.ts'
78 | import ERC677Data from '@rsksmart/erc677/ERC677Data.json'
79 |
80 | const web3 = new Web3('https://public-node.rsk.co')
81 | const rif = new web3.eth.Contract(ERC677Data.abi, ERC677Data.address.rskMainnet) as ERC677
82 | ```
83 |
84 | Replace `web3-v1-contracts` with the proper library version.
85 |
86 | ## Versions
87 |
88 | - Installing v1 will use Solidity v5
89 | - Installing v2 will use Solidity v8
90 |
91 | ---
92 |
93 | RIF Token:
94 | - [Docs](https://developers.rsk.co/rif/token/)
95 | - RSK Mainnet: [0x2acc95758f8b5f583470ba265eb685a8f45fc9d5](https://explorer.rsk.co/address/0x2acc95758f8b5f583470ba265eb685a8f45fc9d5)
96 | - RSK Testnet: [0x19F64674D8A5B4E652319F5e239eFd3bc969A1fE](https://explorer.testnet.rsk.co/address/0x19F64674D8A5B4E652319F5e239eFd3bc969A1fE)
97 |
--------------------------------------------------------------------------------
/addresses.json:
--------------------------------------------------------------------------------
1 | {
2 | "RIFToken": {
3 | "rskMainnet": "0x2acc95758f8b5f583470ba265eb685a8f45fc9d5",
4 | "rskTestnet": "0x19f64674D8a5b4e652319F5e239EFd3bc969a1FE"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/contracts/ERC677.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | // Use only for testing purposes
5 |
6 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
7 | import "./IERC677.sol";
8 | import "./IERC677TransferReceiver.sol";
9 |
10 | contract ERC677 is IERC677, ERC20 {
11 | constructor(
12 | address initialAccount,
13 | uint256 initialBalance,
14 | string memory tokenName,
15 | string memory tokenSymbol
16 | ) ERC20(tokenName, tokenSymbol) {
17 | _mint(initialAccount, initialBalance);
18 | }
19 |
20 | /**
21 | * ERC-677's only method implementation
22 | * See https://github.com/ethereum/EIPs/issues/677 for details
23 | */
24 | function transferAndCall(
25 | address to,
26 | uint256 value,
27 | bytes memory data
28 | ) external override returns (bool) {
29 | bool result = super.transfer(to, value);
30 | if (!result) return false;
31 |
32 | emit Transfer(msg.sender, to, value, data);
33 |
34 | IERC677TransferReceiver receiver = IERC677TransferReceiver(to);
35 | // slither-disable-next-line unused-return
36 | receiver.tokenFallback(msg.sender, value, data);
37 |
38 | // IMPORTANT: the ERC-677 specification does not say
39 | // anything about the use of the receiver contract's
40 | // tokenFallback method return value. Given
41 | // its return type matches with this method's return
42 | // type, returning it could be a possibility.
43 | // We here take the more conservative approach and
44 | // ignore the return value, returning true
45 | // to signal a succesful transfer despite tokenFallback's
46 | // return value -- fact being tokens are transferred
47 | // in any case.
48 | return true;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/contracts/ERC677TransferReceiverTest.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | import "./IERC677TransferReceiver.sol";
5 |
6 | /*
7 | * Contract interface for receivers of tokens that
8 | * comply with ERC-677.
9 | * See https://github.com/ethereum/EIPs/issues/677 for details.
10 | */
11 | contract ERC677TransferReceiverTest is IERC677TransferReceiver {
12 | event Test(address from, uint256 amount, bytes data);
13 |
14 | function tokenFallback(
15 | address from,
16 | uint256 amount,
17 | bytes calldata data
18 | ) external override returns (bool) {
19 | emit Test(from, amount, data);
20 | return true;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/contracts/IERC677.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5 |
6 | interface IERC677 is IERC20 {
7 | function transferAndCall(
8 | address to,
9 | uint256 value,
10 | bytes memory data
11 | ) external returns (bool ok);
12 |
13 | event Transfer(address indexed from, address indexed to, uint256 value, bytes data);
14 | }
15 |
--------------------------------------------------------------------------------
/contracts/IERC677TransferReceiver.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | /*
5 | * Contract interface for receivers of tokens that
6 | * comply with ERC-677.
7 | * See https://github.com/ethereum/EIPs/issues/677 for details.
8 | */
9 | interface IERC677TransferReceiver {
10 | function tokenFallback(
11 | address from,
12 | uint256 amount,
13 | bytes calldata data
14 | ) external returns (bool);
15 | }
16 |
--------------------------------------------------------------------------------
/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | contract Migrations {
5 | address public owner;
6 | uint256 public lastCompletedMigration;
7 |
8 | constructor() {
9 | owner = msg.sender;
10 | }
11 |
12 | modifier restricted() {
13 | require(msg.sender == owner, "Not owner");
14 | _;
15 | }
16 |
17 | function setCompleted(uint256 completed) external restricted {
18 | lastCompletedMigration = completed;
19 | }
20 |
21 | function upgrade(address newAddress) external restricted {
22 | Migrations upgraded = Migrations(newAddress);
23 | upgraded.setCompleted(lastCompletedMigration);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/datagen.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 |
3 | const addresses = require('./addresses');
4 |
5 | const erc677Build = require('./build/contracts/ERC677');
6 |
7 | const erc677Data = {
8 | abi: erc677Build.abi,
9 | bytecode: erc677Build.bytecode,
10 | address: {
11 | rskMainnet: addresses.RIFToken.rskMainnet,
12 | rskTestnet: addresses.RIFToken.rskTestnet,
13 | },
14 | };
15 |
16 | fs.writeFileSync('./ERC677Data.json', JSON.stringify(erc677Data));
17 |
--------------------------------------------------------------------------------
/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | const Migrations = artifacts.require("Migrations");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Migrations);
5 | };
6 |
--------------------------------------------------------------------------------
/migrations/2_erc677.js:
--------------------------------------------------------------------------------
1 | const ERC677 = artifacts.require("ERC677");
2 |
3 | module.exports = function(deployer, _, accounts) {
4 | deployer.deploy(
5 | ERC677,
6 | accounts[0],
7 | web3.utils.toBN('1000000000000000000000'),
8 | 'RIFOS',
9 | 'RIF',
10 | );
11 | };
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@rsksmart/erc677",
3 | "version": "2.0.0",
4 | "description": "ERC-677 Token Implementation",
5 | "files": [
6 | "/contracts",
7 | "!/contracts/Migrations.sol",
8 | "/ERC677Data.json",
9 | "/types"
10 | ],
11 | "scripts": {
12 | "test": "npx truffle test",
13 | "coverage": "npx truffle run coverage",
14 | "lint": "npx prettier --list-different 'contracts/**/*.sol' 'test/**/*.test.js'",
15 | "lint:fix": "npx prettier --write 'contracts/**/*.sol' 'test/**/*.test.js'",
16 | "prepublish": "npx truffle compile && node ./datagen.js && npm run types-generation",
17 | "types-generation": "typechain --target=web3-v1 '*Data.json' && typechain --target=web3-v2 '*Data.json' && typechain --target=truffle '*Data.json' && typechain --target=ethers '*Data.json'"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "git+https://github.com/rnsdomains/erc677.git"
22 | },
23 | "keywords": [
24 | "rsk",
25 | "rif"
26 | ],
27 | "author": "ilanolkies",
28 | "license": "MIT",
29 | "bugs": {
30 | "url": "https://github.com/rnsdomains/erc677/issues"
31 | },
32 | "homepage": "https://github.com/rnsdomains/erc677#readme",
33 | "dependencies": {
34 | "@openzeppelin/contracts": "^4.0.0"
35 | },
36 | "devDependencies": {
37 | "@openzeppelin/test-helpers": "^0.5.4",
38 | "prettier": "^1.19.1",
39 | "prettier-plugin-solidity": "^1.0.0-beta.9",
40 | "solidity-coverage": "^0.7.16",
41 | "truffle": "^5.3.2",
42 | "typechain": "^1.0.5",
43 | "typechain-target-ethers": "^1.0.4",
44 | "typechain-target-truffle": "^1.0.2",
45 | "typechain-target-web3-v1": "^1.0.4",
46 | "typechain-target-web3-v2": "^1.0.0"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/slither.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "detectors_to_exclude": "solc-version",
3 | "filter_paths": "node_modules"
4 | }
5 |
--------------------------------------------------------------------------------
/test/erc677.test.js:
--------------------------------------------------------------------------------
1 | const ERC677 = artifacts.require("ERC677");
2 | const ERC677TransferReceiverTest = artifacts.require("ERC677TransferReceiverTest");
3 |
4 | const { expectEvent } = require("@openzeppelin/test-helpers");
5 |
6 | contract("ERC677", async accounts => {
7 | let erc677, receiver;
8 |
9 | beforeEach(async () => {
10 | erc677 = await ERC677.new(accounts[0], web3.utils.toBN("1000000000000000000000"), "RIFOS", "RIF");
11 |
12 | receiver = await ERC677TransferReceiverTest.new();
13 | });
14 |
15 | it("should emit received data", async () => {
16 | const from = accounts[0];
17 | const to = receiver.address;
18 | const amount = web3.utils.toBN("10");
19 | const data = "0x0011223344556677";
20 |
21 | const { tx } = await erc677.transferAndCall(to, amount, data);
22 |
23 | expectEvent.inTransaction(tx, receiver, "Test", { from, amount, data });
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/truffle-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | compilers: {
3 | solc: {
4 | version: "0.8.3"
5 | }
6 | },
7 | plugins: ["solidity-coverage"]
8 | }
9 |
--------------------------------------------------------------------------------