Skip to content

Commit

Permalink
feat Consolidate logic (SC-5004) (#24)
Browse files Browse the repository at this point in the history
* feat: consolidate all erc20 logic

* fix: rm unused vm and invariant test files

* feat: update README
  • Loading branch information
Lucas Manuel authored Mar 10, 2022
1 parent 552d0cc commit fd0cfde
Show file tree
Hide file tree
Showing 11 changed files with 267 additions and 538 deletions.
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@

**DISCLAIMER: This code has NOT been externally audited and is actively being developed. Please do not use in production without taking the appropriate steps to ensure maximum security.**

<!-- TODO: Update this documentation to reflect new ERC20Permit implementation. -->
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:
- `address(0)` checks on `_transfer`
- `permit()`
- `increaseAllowance`
- `decreaseAllowance`
- `push`
- `pull`

This was intentional, as this ERC-20 was intended to have the minimum functionality necessary, allowing for maximum extendability and customizability.
This was intentional, as this ERC-20 was intended to have the minimum functionality necessary, allowing for maximum extendability and customizability.

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

To clone, set up and run tests:
```
Expand Down
43 changes: 43 additions & 0 deletions contracts/ERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import { IERC20 } from "./interfaces/IERC20.sol";
*/
contract ERC20 is IERC20 {

/**************/
/*** ERC-20 ***/
/**************/

string public override name;
string public override symbol;

Expand All @@ -20,6 +24,15 @@ contract ERC20 is IERC20 {

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

/****************/
/*** ERC-2612 ***/
/****************/

// PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 amount,uint256 nonce,uint256 deadline)");
bytes32 public constant override PERMIT_TYPEHASH = 0xfc77c2b9d30fe91687fd39abb7d16fcdfe1472d065740051ab8b13e4bf4a617f;

mapping (address => uint256) public override nonces;

/**
* @param name_ The name of the token.
* @param symbol_ The symbol of the token.
Expand Down Expand Up @@ -50,6 +63,20 @@ contract ERC20 is IERC20 {
return true;
}

function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external override {
require(deadline >= block.timestamp, "ERC20:P:EXPIRED");
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, amount, nonces[owner]++, deadline))
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
require(recoveredAddress == owner && owner != address(0), "ERC20:P:INVALID_SIGNATURE");
_approve(owner, spender, amount);
}

function transfer(address recipient_, uint256 amount_) external override returns (bool success_) {
_transfer(msg.sender, recipient_, amount_);
return true;
Expand All @@ -61,6 +88,22 @@ contract ERC20 is IERC20 {
return true;
}

/**********************/
/*** View Functions ***/
/**********************/

function DOMAIN_SEPARATOR() public view override returns (bytes32 domainSeparator_) {
return keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256(bytes("1")),
block.chainid,
address(this)
)
);
}

/**************************/
/*** Internal Functions ***/
/**************************/
Expand Down
132 changes: 0 additions & 132 deletions contracts/ERC20Permit.sol

This file was deleted.

109 changes: 76 additions & 33 deletions contracts/interfaces/IERC20.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.7;

/// @title Interface of the ERC20 standard as defined in the EIP.
/// @title Interface of the ERC20 standard as defined in the EIP, including ERC-2612 permit functionality.
interface IERC20 {

/**************/
/*** Events ***/
/**************/

/**
* @dev Emits an event indicating that tokens have moved from one account to another.
* @param owner_ Account that tokens have moved from.
Expand All @@ -20,38 +24,9 @@ interface IERC20 {
*/
event Approval(address indexed owner_, address indexed spender_, uint256 amount_);

/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory name_);

/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory symbol_);

/**
* @dev Returns the decimal precision used by the token.
*/
function decimals() external view returns (uint8 decimals_);

/**
* @dev Returns the total amount of tokens in existence.
*/
function totalSupply() external view returns (uint256 totalSupply_);

/**
* @dev Returns the amount of tokens owned by a given account.
* @param account_ Account that owns the tokens.
*/
function balanceOf(address account_) external view returns (uint256 balance_);

/**
* @dev Function that returns the allowance that one account has given another over their tokens.
* @param owner_ Account that tokens are approved from.
* @param spender_ Account that tokens are approved for.
*/
function allowance(address owner_, address spender_) external view returns (uint256 allowance_);
/**************************/
/*** External Functions ***/
/**************************/

/**
* @dev Function that allows one account to set the allowance of another account over their tokens.
Expand Down Expand Up @@ -80,6 +55,18 @@ interface IERC20 {
*/
function increaseAllowance(address spender_, uint256 addedAmount_) external returns (bool success_);

/**
* @dev Approve by signature.
* @param owner_ Owner address that signed the permit.
* @param spender_ Spender of the permit.
* @param amount_ Permit approval spend limit.
* @param deadline_ Deadline after which the permit is invalid.
* @param v_ ECDSA signature v component.
* @param r_ ECDSA signature r component.
* @param s_ ECDSA signature s component.
*/
function permit(address owner_, address spender_, uint amount_, uint deadline_, uint8 v_, bytes32 r_, bytes32 s_) external;

/**
* @dev Moves an amount of tokens from `msg.sender` to a specified account.
* Emits a {Transfer} event.
Expand All @@ -100,4 +87,60 @@ interface IERC20 {
*/
function transferFrom(address owner_, address recipient_, uint256 amount_) external returns (bool success_);

/**********************/
/*** View Functions ***/
/**********************/

/**
* @dev Function that returns the allowance that one account has given another over their tokens.
* @param owner_ Account that tokens are approved from.
* @param spender_ Account that tokens are approved for.
*/
function allowance(address owner_, address spender_) external view returns (uint256 allowance_);

/**
* @dev Returns the amount of tokens owned by a given account.
* @param account_ Account that owns the tokens.
*/
function balanceOf(address account_) external view returns (uint256 balance_);

/**
* @dev Returns the decimal precision used by the token.
*/
function decimals() external view returns (uint8 decimals_);

/**
* @dev Returns the signature domain separator.
* @return domainSeparator_ The domain for the contract.
*/
function DOMAIN_SEPARATOR() external view returns (bytes32 domainSeparator_);

/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory name_);

/**
* @dev Returns the nonce for the given owner.
* @param owner The address of the owner account.
* @return nonce_ The current nonce.
*/
function nonces(address owner) external view returns (uint256 nonce_);

/**
* @dev Returns the permit type hash.
* @return hash_ The typehash for the commit.
*/
function PERMIT_TYPEHASH() external view returns (bytes32 hash_);

/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory symbol_);

/**
* @dev Returns the total amount of tokens in existence.
*/
function totalSupply() external view returns (uint256 totalSupply_);

}
Loading

0 comments on commit fd0cfde

Please sign in to comment.