├── .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 | logo 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 | Coverage Status 20 | 21 | 22 | npm 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 | --------------------------------------------------------------------------------