Skip to content

Commit b2fd236

Browse files
JGcarvdeluca-mike
andauthored
feat: Standardize README and clean up (#48)
* Update README.md * feat: Standardize README and clean up (#49) * feat: Standard Readme and cleanup * fix: PR Review Co-authored-by: Michael De Luca <[email protected]>
1 parent 0b65626 commit b2fd236

File tree

5 files changed

+70
-45
lines changed

5 files changed

+70
-45
lines changed

README.md

+18-12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
![Foundry CI](https://github.com/maple-labs/erc20/actions/workflows/push-to-main.yml/badge.svg) [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
44

5+
## Overview
6+
57
Basic ERC-20 contract designed to be inherited and extended. Leveraging native overflow checks in solc 0.8 to simplify ERC-20 implementation. It should be noted that this ERC-20 implementation does not include some functionality that is commonly used in other tokens, such as:
68
- `address(0)` checks on `_transfer`
79
- `push`
@@ -11,13 +13,23 @@ This was intentional, as this ERC-20 was intended to have the minimum functional
1113

1214
This token implementation includes ERC-2612 [permit](https://eips.ethereum.org/EIPS/eip-2612) capability as well as `increaseAllowance` and `decreaseAllowance` functions.
1315

14-
To clone, set up and run tests:
15-
```
16-
git clone [email protected]:maple-labs/ERC20.git
17-
forge update
18-
make test
16+
## Setup
17+
18+
This project was built using [Foundry](https://book.getfoundry.sh/). Refer to installation instructions [here](https://github.com/foundry-rs/foundry#installation).
19+
20+
```sh
21+
git clone [email protected]:maple-labs/erc20.git
22+
cd erc20
23+
forge install
1924
```
2025

26+
## Running Tests
27+
28+
- To run all tests: `forge test`
29+
- To run specific tests: `forge test --match <test_name>`
30+
31+
`./scripts/test.sh` is used to enable Foundry profile usage with the `-p` flag. Profiles are used to specify the number of fuzz runs.
32+
2133
## Acknowledgements
2234
These contracts were inspired by and/or directly modified from the following sources:
2335
- [Solmate](https://github.com/Rari-Capital/solmate)
@@ -34,16 +46,10 @@ These contracts were inspired by and/or directly modified from the following sou
3446

3547
For all information related to the ongoing bug bounty for these contracts run by [Immunefi](https://immunefi.com/), please visit this [site](https://immunefi.com/bounty/maple/).
3648

37-
| Severity of Finding | Payout |
38-
|---|---|
39-
| Critical | $50,000 |
40-
| High | $25,000 |
41-
| Medium | $1,000 |
42-
4349
## About Maple
4450
Maple is a decentralized corporate credit market. Maple provides capital to institutional borrowers through globally accessible fixed-income yield opportunities.
4551

46-
For all technical documentation related to the Maple protocol, please refer to the GitHub [wiki](https://github.com/maple-labs/maple-core/wiki).
52+
For all technical documentation related to the Maple protocol, please refer to the GitHub [wiki](https://github.com/maple-labs/maple-core-v2/wiki).
4753

4854
---
4955

contracts/ERC20.sol

+21-19
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ import { IERC20 } from "./interfaces/IERC20.sol";
1818
*/
1919
contract ERC20 is IERC20 {
2020

21-
/**************/
22-
/*** ERC-20 ***/
23-
/**************/
21+
/**************************************************************************************************************************************/
22+
/*** ERC-20 ***/
23+
/**************************************************************************************************************************************/
2424

2525
string public override name;
2626
string public override symbol;
@@ -33,9 +33,9 @@ contract ERC20 is IERC20 {
3333

3434
mapping(address => mapping(address => uint256)) public override allowance;
3535

36-
/****************/
37-
/*** ERC-2612 ***/
38-
/****************/
36+
/**************************************************************************************************************************************/
37+
/*** ERC-2612 ***/
38+
/**************************************************************************************************************************************/
3939

4040
// PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
4141
bytes32 public constant override PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
@@ -53,9 +53,9 @@ contract ERC20 is IERC20 {
5353
decimals = decimals_;
5454
}
5555

56-
/**************************/
57-
/*** External Functions ***/
58-
/**************************/
56+
/**************************************************************************************************************************************/
57+
/*** External Functions ***/
58+
/**************************************************************************************************************************************/
5959

6060
function approve(address spender_, uint256 amount_) public virtual override returns (bool success_) {
6161
_approve(msg.sender, spender_, amount_);
@@ -72,7 +72,9 @@ contract ERC20 is IERC20 {
7272
return true;
7373
}
7474

75-
function permit(address owner_, address spender_, uint256 amount_, uint256 deadline_, uint8 v_, bytes32 r_, bytes32 s_) public virtual override {
75+
function permit(address owner_, address spender_, uint256 amount_, uint256 deadline_, uint8 v_, bytes32 r_, bytes32 s_)
76+
public virtual override
77+
{
7678
require(deadline_ >= block.timestamp, "ERC20:P:EXPIRED");
7779

7880
// Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
@@ -85,17 +87,17 @@ contract ERC20 is IERC20 {
8587

8688
// Nonce realistically cannot overflow.
8789
unchecked {
88-
bytes32 digest = keccak256(
90+
bytes32 digest_ = keccak256(
8991
abi.encodePacked(
9092
"\x19\x01",
9193
DOMAIN_SEPARATOR(),
9294
keccak256(abi.encode(PERMIT_TYPEHASH, owner_, spender_, amount_, nonces[owner_]++, deadline_))
9395
)
9496
);
9597

96-
address recoveredAddress = ecrecover(digest, v_, r_, s_);
98+
address recoveredAddress_ = ecrecover(digest_, v_, r_, s_);
9799

98-
require(recoveredAddress == owner_ && owner_ != address(0), "ERC20:P:INVALID_SIGNATURE");
100+
require(recoveredAddress_ == owner_ && owner_ != address(0), "ERC20:P:INVALID_SIGNATURE");
99101
}
100102

101103
_approve(owner_, spender_, amount_);
@@ -112,9 +114,9 @@ contract ERC20 is IERC20 {
112114
return true;
113115
}
114116

115-
/**********************/
116-
/*** View Functions ***/
117-
/**********************/
117+
/**************************************************************************************************************************************/
118+
/*** View Functions ***/
119+
/**************************************************************************************************************************************/
118120

119121
function DOMAIN_SEPARATOR() public view override returns (bytes32 domainSeparator_) {
120122
return keccak256(
@@ -128,9 +130,9 @@ contract ERC20 is IERC20 {
128130
);
129131
}
130132

131-
/**************************/
132-
/*** Internal Functions ***/
133-
/**************************/
133+
/**************************************************************************************************************************************/
134+
/*** Internal Functions ***/
135+
/**************************************************************************************************************************************/
134136

135137
function _approve(address owner_, address spender_, uint256 amount_) internal {
136138
emit Approval(owner_, spender_, allowance[owner_][spender_] = amount_);

contracts/interfaces/IERC20.sol

+9-9
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ pragma solidity ^0.8.7;
44
/// @title Interface of the ERC20 standard as defined in the EIP, including EIP-2612 permit functionality.
55
interface IERC20 {
66

7-
/**************/
8-
/*** Events ***/
9-
/**************/
7+
/**************************************************************************************************************************************/
8+
/*** Events ***/
9+
/**************************************************************************************************************************************/
1010

1111
/**
1212
* @dev Emitted when one account has set the allowance of another account over their tokens.
@@ -24,9 +24,9 @@ interface IERC20 {
2424
*/
2525
event Transfer(address indexed owner_, address indexed recipient_, uint256 amount_);
2626

27-
/**************************/
28-
/*** External Functions ***/
29-
/**************************/
27+
/**************************************************************************************************************************************/
28+
/*** External Functions ***/
29+
/**************************************************************************************************************************************/
3030

3131
/**
3232
* @dev Function that allows one account to set the allowance of another account over their tokens.
@@ -87,9 +87,9 @@ interface IERC20 {
8787
*/
8888
function transferFrom(address owner_, address recipient_, uint256 amount_) external returns (bool success_);
8989

90-
/**********************/
91-
/*** View Functions ***/
92-
/**********************/
90+
/**************************************************************************************************************************************/
91+
/*** View Functions ***/
92+
/**************************************************************************************************************************************/
9393

9494
/**
9595
* @dev Returns the allowance that one account has given another over their tokens.

contracts/test/ERC20.t.sol

+21-4
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,11 @@ contract ERC20PermitTest is TestUtils {
265265
uint256 startingNonce = _token.nonces(_owner);
266266
uint256 expectedNonce = startingNonce + 1;
267267

268-
( uint8 v, bytes32 r, bytes32 s ) = _getValidPermitSignature(address(_token), _owner, _spender, amount_, startingNonce, _deadline, _skOwner);
268+
(
269+
uint8 v,
270+
bytes32 r,
271+
bytes32 s
272+
) = _getValidPermitSignature(address(_token), _owner, _spender, amount_, startingNonce, _deadline, _skOwner);
269273

270274
_user.erc20_permit(address(_token), _owner, _spender, amount_, _deadline, v, r, s);
271275

@@ -371,7 +375,8 @@ contract ERC20PermitTest is TestUtils {
371375
function test_permit_badV() public {
372376
// Get valid signature. The `v` value is the expected v value that will cause `permit` to succeed, and must be 27 or 28.
373377
// Any other value should fail.
374-
// If v is 27, then 28 should make it past the MALLEABLE require, but should result in an invalid signature, and vice versa when v is 28.
378+
// If v is 27, then 28 should make it past the MALLEABLE require, but should result in an invalid signature,
379+
// and vice versa when v is 28.
375380
( uint8 v, bytes32 r, bytes32 s ) = _getValidPermitSignature(address(_token), _owner, _spender, 1000, 0, _deadline, _skOwner);
376381

377382
for (uint8 i; i <= type(uint8).max; i++) {
@@ -391,7 +396,9 @@ contract ERC20PermitTest is TestUtils {
391396
}
392397

393398
// Returns an ERC-2612 `permit` digest for the `owner` to sign
394-
function _getDigest(address token_, address owner_, address spender_, uint256 amount_, uint256 nonce_, uint256 deadline_) internal view returns (bytes32 digest_) {
399+
function _getDigest(address token_, address owner_, address spender_, uint256 amount_, uint256 nonce_, uint256 deadline_)
400+
internal view returns (bytes32 digest_)
401+
{
395402
return keccak256(
396403
abi.encodePacked(
397404
'\x19\x01',
@@ -402,7 +409,17 @@ contract ERC20PermitTest is TestUtils {
402409
}
403410

404411
// Returns a valid `permit` signature signed by this contract's `owner` address
405-
function _getValidPermitSignature(address token_, address owner_, address spender_, uint256 amount_, uint256 nonce_, uint256 deadline_, uint256 ownerSk_) internal returns (uint8 v_, bytes32 r_, bytes32 s_) {
412+
function _getValidPermitSignature(
413+
address token_,
414+
address owner_,
415+
address spender_,
416+
uint256 amount_,
417+
uint256 nonce_,
418+
uint256 deadline_,
419+
uint256 ownerSk_
420+
)
421+
internal returns (uint8 v_, bytes32 r_, bytes32 s_)
422+
{
406423
return vm.sign(ownerSk_, _getDigest(token_, owner_, spender_, amount_, nonce_, deadline_));
407424
}
408425

contracts/test/mocks/MockERC20.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { ERC20 } from "../../ERC20.sol";
55

66
contract MockERC20 is ERC20 {
77

8-
constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_, decimals_) { }
8+
constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_, decimals_) {}
99

1010
function mint(address recipient_, uint256 amount_) external {
1111
_mint(recipient_, amount_);

0 commit comments

Comments
 (0)