Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
alcueca committed Dec 7, 2020
0 parents commit ff70748
Show file tree
Hide file tree
Showing 19 changed files with 1,117 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dist
node_modules
coverage
31 changes: 31 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
👋 Hi! This file was autogenerated by tslint-to-eslint-config.
https://github.com/typescript-eslint/tslint-to-eslint-config
It represents the closest reasonable ESLint configuration to this
project's original TSLint configuration.
We recommend eventually switching this configuration to extend from
the recommended rulesets in typescript-eslint.
https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FAQs.md
Happy linting! 💖
*/
module.exports = {
"env": {
"es6": true,
"node": true
},
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "tsconfig.json",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
]
};
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.sol linguist-language=Solidity
30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Temp & IDE files
.vscode/
*~
*.swp
*.swo

# Buidler files
cache
artifacts
node_modules/
output/

# Truffle files
.infuraKey
.secret
build/

# Solidity-coverage
coverage/
.coverage_contracts/
coverage.json

# Yarn
yarn-error.log

# NPM
package-lock.json

# Crytic
crytic-export/
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"semi": false,
"singleQuote": true,
"printWidth": 120
}
4 changes: 4 additions & 0 deletions .solcover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
skipFiles: [
]
}
11 changes: 11 additions & 0 deletions .solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "solhint:recommended",
"plugins": [],
"rules": {
"avoid-throw": "off",
"avoid-suicide": "error",
"avoid-sha3": "warn",
"compiler-version": "off",
"no-empty-blocks": "off"
}
}
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ERC20 Flash

This project is the reference implementation the the [ERC 3156 Flash Loan](https://github.com/ethereum/EIPs/pull/3156) standard.

The contracts included inherit from OpenZeppelin's ERC20.

## How to Use

`ERC20FlashLoan` and `ERC20FlashMint` are `ERC20` contracts. You can just inherit from them and you are done from the smart contracts point of view.

```
contract MyContract is ERC20FlashMint {
constructor (string memory _name, string memory _symbol, uint256 _fee) public ERC20FlashMint(_name, _symbol, _fee) {...}
...
}
```

```
contract MyContract is ERC20FlashLoan {
constructor (string memory _name, string memory _symbol, IERC20 _asset, uint256 _fee) public ERC20FlashLoan(_name, _symbol, _asset, _fee) {...}
...
}
```

The `_fee` parameter is a divisor to be applied on the flash loaned values. The `receiver` of the `flashLoan` will have to pay back `value + value/fee`.
29 changes: 29 additions & 0 deletions buidler.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { usePlugin } from "@nomiclabs/buidler/config";

usePlugin("@nomiclabs/buidler-truffle5");
usePlugin("solidity-coverage");
usePlugin("buidler-gas-reporter");

export default {
defaultNetwork: "buidlerevm",
solc: {
version: "0.7.5",
optimizer: {
enabled: true,
runs: 200
},
},
gasReporter: {
enabled: true
},
paths: {
artifacts: "./build",
coverage: "./coverage",
coverageJson: "./coverage.json",
},
networks: {
coverage: {
url: "http://127.0.0.1:8555",
},
},
};
2 changes: 2 additions & 0 deletions codechecks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
checks:
- name: eth-gas-reporter/codechecks
41 changes: 41 additions & 0 deletions contracts/ERC20FlashLoan.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.7.5;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";


interface flashBorrowerLike {
function onFlashLoan(address user, uint256 value, uint256 fee, bytes calldata) external;
}

/**
* @author Alberto Cuesta Cañada
* @dev Extension of {ERC20} that allows flash lending.
*/
contract ERC20FlashLoan is ERC20 {
using SafeMath for uint256;

IERC20 public immutable asset;
uint256 public fee;

constructor(string memory name, string memory symbol, IERC20 asset_, uint256 fee_) ERC20(name, symbol) {
asset = asset_;
fee = fee_;
}

/**
* @dev Loan `value` tokens to `receiver`, which needs to return them plus a 0.1% fee to this contract within the same transaction.
* @param receiver The contract receiving the tokens, needs to implement the `onFlashLoan(address user, uint256 value, uint256 fee, bytes calldata)` interface.
* @param value The amount of tokens lent.
* @param data A data parameter to be passed on to the `receiver` for any custom use.
*/
function flashLoan(address receiver, uint256 value, bytes calldata data) external {
uint256 _fee = value.div(fee);
uint256 supplyTarget = totalSupply().add(_fee);
asset.transfer(receiver, value);
flashBorrowerLike(receiver).onFlashLoan(msg.sender, value, _fee, data);
require(totalSupply() >= supplyTarget);
}
}
37 changes: 37 additions & 0 deletions contracts/ERC20FlashMint.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.7.5;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";


interface flashBorrowerLike {
function onFlashLoan(address user, uint256 value, uint256 fee, bytes calldata) external;
}

/**
* @author Alberto Cuesta Cañada
* @dev Extension of {ERC20} that allows flash minting.
*/
contract ERC20FlashMint is ERC20 {
using SafeMath for uint256;

uint256 public fee;

constructor (string memory name, string memory symbol, uint256 fee_) ERC20(name, symbol) {
fee = fee_;
}

/**
* @dev Loan `value` tokens to `receiver`, which needs to return them plus a 0.1% fee to this contract within the same transaction.
* @param receiver The contract receiving the tokens, needs to implement the `onFlashLoan(address user, uint256 value, uint256 fee, bytes calldata)` interface.
* @param value The amount of tokens lent.
* @param data A data parameter to be passed on to the `receiver` for any custom use.
*/
function flashLoan(address receiver, uint256 value, bytes calldata data) external {
uint256 _fee = value.div(fee);
_mint(receiver, value);
flashBorrowerLike(receiver).onFlashLoan(msg.sender, value, _fee, data);
_burn(address(this), value.add(_fee));
}
}
5 changes: 5 additions & 0 deletions migrations/1_initial_migration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Migrations = artifacts.require('Migrations');

module.exports = (deployer) => {
deployer.deploy(Migrations);
};
64 changes: 64 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"name": "erc20flash",
"version": "0.0.1",
"description": "Solidity contracts implementing flash lending",
"author": "Alberto Cuesta Cañada",
"engines": {
"node": ">= 10.12.0",
"npm": ">= 6.4.0",
"yarn": ">= 1.10.0"
},
"files": [
"/contracts/ERC20FlashLoan.sol",
"/contracts/ERC20FlashMint.sol"
],
"keywords": [
"solidity",
"ethereum",
"smart",
"contracts",
"security"
],
"scripts": {
"build": "buidler compile",
"test": "buidler test test/*.ts",
"ganache": "./scripts/ganache.sh",
"deploy:ganache": "yarn ganache && truffle migrate",
"coverage": "buidler coverage --network coverage --temp build --testfiles 'test/*.ts'",
"lint:js": "prettier ./test/**/*.js --write",
"lint:sol": "solhint -f table contracts/**/*.sol"
},
"dependencies": {
"@openzeppelin/contracts": "3.3.0"
},
"devDependencies": {
"@nomiclabs/buidler": "^1.3.8",
"@nomiclabs/buidler-truffle5": "^1.3.4",
"@nomiclabs/buidler-web3": "^1.3.4",
"@openzeppelin/contracts": "3.3.0",
"@openzeppelin/test-helpers": "^0.5.6",
"@truffle/hdwallet-provider": "^1.0.40",
"@types/mocha": "^8.0.0",
"buidler-gas-reporter": "0.1.4-beta.4",
"chai": "4.2.0",
"ethereumjs-util": "^7.0.3",
"ethers": "^5.0.7",
"ganache-time-traveler": "^1.0.14",
"mocha": "^7.1.0",
"prettier": "^2.0.5",
"solhint": "^3.2.0",
"solidity-coverage": "^0.7.9",
"truffle": "^5.1.39",
"truffle-typings": "^1.0.8",
"ts-node": "^8.10.2",
"typescript": "^3.9.7"
},
"repository": {
"type": "git",
"url": "git+https://github.com/albertocuestacanada/ERC20Flash.git"
},
"license": "GPL-3.0-or-later",
"bugs": {
"url": "https://github.com/albertocuestacanada/ERC20Flash/issues"
},
"homepage": "https://github.com/albertocuestacanada/ERC20Flash"}
21 changes: 21 additions & 0 deletions test/erc20flash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const ERC20FlashLoan = artifacts.require('ERC20FlashLoan')
const ERC20FlashMint = artifacts.require('ERC20FlashMint')

// @ts-ignore
import { expectRevert } from '@openzeppelin/test-helpers'

type Contract = any

contract('ERC20FlashMint', async (accounts: string[]) => {
let [owner, user] = accounts

let token: Contract
let name: string

beforeEach(async () => {
token = await ERC20FlashMint.new("Test", "TST", 1000, { from: owner })
})

it('tests to be added', async () => {
})
})
Loading

0 comments on commit ff70748

Please sign in to comment.