Skip to content

Commit

Permalink
Merge pull request #44 from Into-the-Fathom/dev
Browse files Browse the repository at this point in the history
1.0.0
  • Loading branch information
BaldyAsh committed Feb 15, 2023
2 parents 52ade6a + c5ba9ca commit b95c4a1
Show file tree
Hide file tree
Showing 159 changed files with 8,835 additions and 6,429 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ privateKey
yarn.lock
package-lock.json
bin

subgraph/build/
subgraph/generated/
subgraph/node_modules/
3 changes: 1 addition & 2 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"bracketSpacing": true,
"explicitTypes": "preserve",
"printWidth": 120,
"printWidth": 150,
"semi": true,
"singleQuote": false,
"tabWidth": 4,
Expand Down
62 changes: 61 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,61 @@
# Fathom DAO Smart Contracts
# Fathom DAO Smart Contracts

Fathom project staking, governance and treasury smart contracts for EVM compatible chains.
[Protocol description](./docs/PROTOCOL.md)

## Package version requirements for your machine:

- node v16.4.0
- npm v7.18.1
- CoralX v0.2.0
- Solidity =0.8.13 (solc)
- Ganache CLI v6.12.2 (ganache-core: 2.13.2)

## Setup

The smart contracts are written in [Solidity](https://github.com/ethereum/solidity) and tested/deployed using [CoralX](https://github.com/Securrency-OSS/CoralX).

```bash
# Install nodejs:
$ sudo apt install nodejs

# Install npm:
$ sudo apt install npm

# Intall CoralX from the Securrency private registry
# Install CoralX package globally:
$ npm install -g coral-x

# Install ganache-cli:
$ npm install -g ganache-cli

# Install local node dependencies:
$ npm install

# Install Solc (https://docs.soliditylang.org/en/v0.8.13/installing-solidity.html)
$ curl -o /usr/bin/solc -fL https://github.com/ethereum/solidity/releases/download/v0.8.13/solc-static-linux \
&& chmod u+x /usr/bin/solc

# Create file with "privateKey" private key in the root direcory (use this only for tests):
$ echo -n PRIVATE_KEY > privateKey

# Run ganache with predefined accounts:
$ ganache-cli -m MNEMONIC --gasLimit 12500000

# now you can run tests:
$ npm run test

# Deploy to the local node
$ npm run migrate-reset

# Deploy to the public testnet
# For a deployment to the public testnet make sure that you have testnet coins
# Deploy to the apothem
$ npm run migrate-reset-apothem

# Deploy to the goerli
$ npm run migrate-reset-goerli

# Deploy to the xdc
$ npm run migrate-reset-xdc
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Original Copyright OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
// Copyright Fathom 2022

pragma solidity ^0.8.1;
pragma solidity 0.8.16;

/**
* @dev Collection of functions related to the address type
Expand Down Expand Up @@ -196,6 +196,14 @@ library Address {
return verifyCallResult(success, returndata, errorMessage);
}

function getExtCodeHash(address target) internal view returns (bytes32) {
bytes32 codeHash;
assembly {
codeHash := extcodehash(target)
}
return codeHash;
}

/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Original Copyright OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
// Copyright Fathom 2022

pragma solidity ^0.8.0;
pragma solidity 0.8.16;

/**
* @dev Provides information about the current execution context, including the
Expand Down
113 changes: 113 additions & 0 deletions contracts/common/SafeERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity 0.8.16;

import "../dao/tokens/ERC20/IERC20.sol";
import "../dao/tokens/ERC20/extensions/IERC20Permit.sol";
import "./Address.sol";

/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;

function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}

function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}

/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}

function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}

function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}

function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}

/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.

bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
67 changes: 67 additions & 0 deletions contracts/common/SafeERC20Staking.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity 0.8.16;

import "../dao/tokens/ERC20/IERC20.sol";
import "../dao/tokens/ERC20/extensions/IERC20Permit.sol";
import "./Address.sol";

/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20Staking {
using Address for address;

function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}

/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}

/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.

bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Original Copyright OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)
// Copyright Fathom 2022

pragma solidity ^0.8.0;
pragma solidity 0.8.16;

/**
* @dev String operations.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
// Original Copyright OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)
// Copyright Fathom 2022

pragma solidity ^0.8.0;
pragma solidity 0.8.16;

import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
import "../Context.sol";
import "../Strings.sol";
import "../introspection/ERC165.sol";

/**
* @dev Contract module that allows children to implement role-based access
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Original Copyright OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
// Copyright Fathom 2022

pragma solidity ^0.8.0;
pragma solidity 0.8.16;

/**
* @dev External interface of AccessControl declared to support ERC165 detection.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Original Copyright OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol)
// Copyright Fathom 2022

pragma solidity ^0.8.0;
pragma solidity 0.8.16;

import "../Strings.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
// Original Copyright OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)
// Original Copyright OpenZeppelin Contracts v4.4.1 (utils/cryptography/EIP712.sol)
// Copyright Fathom 2022

pragma solidity ^0.8.0;
pragma solidity 0.8.16;

import "./ECDSA.sol";

Expand Down Expand Up @@ -54,22 +54,28 @@ abstract contract EIP712 {
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
bytes32 typeHash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_CHAIN_ID = getChainID();
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
}

function getChainID() internal view returns (uint256) {
uint256 id;
assembly {
id := chainid()
}
return id;
}

/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
if (address(this) == _CACHED_THIS && getChainID() == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
Expand Down Expand Up @@ -100,6 +106,6 @@ abstract contract EIP712 {
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
return keccak256(abi.encode(typeHash, nameHash, versionHash, getChainID(), address(this)));
}
}
Loading

0 comments on commit b95c4a1

Please sign in to comment.