Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/audits #49

Merged
merged 7 commits into from
Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,3 @@
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/Openzeppelin/openzeppelin-contracts
[submodule "lib/solmate"]
path = lib/solmate
url = https://github.com/transmissions11/solmate
1 change: 0 additions & 1 deletion lib/solmate
Submodule solmate deleted from 8d910d
39 changes: 18 additions & 21 deletions src/Funnel.sol
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity 0.8.17;

import { ERC20 } from "solmate/tokens/ERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { IERC20Metadata } from "openzeppelin-contracts/interfaces/IERC20Metadata.sol";
import { Address } from "openzeppelin-contracts/utils/Address.sol";
import { IERC1363Receiver } from "openzeppelin-contracts/interfaces/IERC1363Receiver.sol";
import { IERC1271 } from "openzeppelin-contracts/interfaces/IERC1271.sol";
import { Strings } from "openzeppelin-contracts/utils/Strings.sol";
import { Initializable } from "openzeppelin-contracts/proxy/utils/Initializable.sol";

import { IFunnel } from "./interfaces/IFunnel.sol";
import { IERC20 } from 'openzeppelin-contracts/token/ERC20/IERC20.sol';
import { SafeERC20 } from 'openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol';
zlace0x marked this conversation as resolved.
Show resolved Hide resolved
import { IERC5827 } from "./interfaces/IERC5827.sol";
import { IERC5827Proxy } from "./interfaces/IERC5827Proxy.sol";
import { IERC5827Spender } from "./interfaces/IERC5827Spender.sol";
import { IERC5827Payable } from "./interfaces/IERC5827Payable.sol";
import { MetaTxContext } from "./lib/MetaTxContext.sol";
import { Nonces } from "./lib/Nonces.sol";
import { EIP712 } from "./lib/EIP712.sol";
import { NativeMetaTransaction } from "./lib/NativeMetaTransaction.sol";

contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable {
using SafeTransferLib for ERC20;
using SafeERC20 for IERC20;

/*//////////////////////////////////////////////////////////////
EIP-5827 STORAGE
//////////////////////////////////////////////////////////////*/

ERC20 private _baseToken;
IERC20 private _baseToken;

struct RenewableAllowance {
uint256 maxAmount;
Expand All @@ -47,18 +43,19 @@ contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable

bytes32 internal INITIAL_DOMAIN_SEPARATOR;

bytes32 internal immutable PERMIT_RENEWABLE_TYPEHASH =
bytes32 internal constant PERMIT_RENEWABLE_TYPEHASH =
keccak256(
"PermitRenewable(address owner,address spender,uint256 value,uint256 recoveryRate,uint256 nonce,uint256 deadline)"
);

bytes32 internal immutable PERMIT_TYPEHASH =
bytes32 internal constant PERMIT_TYPEHASH =
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
);

function initialize(address _token) public initializer {
_baseToken = ERC20(_token);
function initialize(address _token) external initializer {
require(_token != address(0));
_baseToken = IERC20(_token);

INITIAL_CHAIN_ID = block.chainid;

Expand Down Expand Up @@ -113,7 +110,7 @@ contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
) external virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

uint256 nonce;
Expand All @@ -139,7 +136,7 @@ contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
) external virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

uint256 nonce;
Expand All @@ -165,8 +162,7 @@ contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable
}

function approve(address _spender, uint256 _value)
public
override
external
returns (bool success)
{
_approve(_msgSender(), _spender, _value, 0);
Expand All @@ -177,7 +173,7 @@ contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable
address _spender,
uint256 _value,
uint256 _recoveryRate
) public returns (bool success) {
) external returns (bool success) {
_approve(_msgSender(), _spender, _value, _recoveryRate);
return true;
}
Expand Down Expand Up @@ -228,7 +224,7 @@ contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable
/// @return amount initial and maximum allowance given to spender
/// @return recoveryRate recovery amount per second
function renewableAllowance(address _owner, address _spender)
public
external
view
returns (uint256 amount, uint256 recoveryRate)
{
Expand Down Expand Up @@ -381,7 +377,7 @@ contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable
return address(_baseToken);
}

function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
return
interfaceId == type(IERC5827).interfaceId ||
interfaceId == type(IERC5827Payable).interfaceId ||
Expand All @@ -398,7 +394,8 @@ contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable
}

function transfer(address to, uint256 amount) external returns (bool) {
return _baseToken.transferFrom(_msgSender(), to, amount);
_baseToken.safeTransferFrom(_msgSender(), to, amount);
return true;
}

fallback() external {
Expand Down
33 changes: 18 additions & 15 deletions src/FunnelFactory.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity 0.8.17;

import { IFunnelFactory } from "./interfaces/IFunnelFactory.sol";
import { IERC5827 } from "./interfaces/IERC5827.sol";
import { IERC5827Proxy } from "./interfaces/IERC5827Proxy.sol";
import { Funnel } from "./Funnel.sol";
import { Clones } from "openzeppelin-contracts/proxy/Clones.sol";
Expand All @@ -16,22 +15,24 @@ contract FunnelFactory is IFunnelFactory {
address public funnelImplementation;

constructor(address _funnelImplementation) {
require(_funnelImplementation != address(0));
funnelImplementation = _funnelImplementation;
}

/**
* @dev Deploys a new Funnel contract
* Throws if `_tokenAddress` has already been deployed
*/
function deployFunnelForToken(address _tokenAddress)
public
returns (address _funnelAddress)
{
function deployFunnelForToken(
address _tokenAddress
) external returns (address _funnelAddress) {
if (deployments[_tokenAddress] != address(0)) {
revert FunnelAlreadyDeployed();
}

if (_tokenAddress.code.length == 0) revert InvalidToken();
if (_tokenAddress.code.length == 0) {
revert InvalidToken();
}

_funnelAddress = _deployFunnel(_tokenAddress);
deployments[_tokenAddress] = _funnelAddress;
Expand All @@ -55,11 +56,9 @@ contract FunnelFactory is IFunnelFactory {
* @dev Returns the Funnel contract address for a given token address
* Reverts with FunnelNotDeployed if `_tokenAddress` has not been deployed
*/
function getFunnelForToken(address _tokenAddress)
public
view
returns (address _funnelAddress)
{
function getFunnelForToken(
address _tokenAddress
) public view returns (address _funnelAddress) {
if (deployments[_tokenAddress] == address(0)) {
revert FunnelNotDeployed();
}
Expand All @@ -70,12 +69,16 @@ contract FunnelFactory is IFunnelFactory {
/**
* @dev Returns true if contract address is a deployed Funnel contract
*/
function isFunnel(address _funnelAddress) public view returns (bool) {
function isFunnel(address _funnelAddress) external view returns (bool) {
// Not a deployed contract
if (_funnelAddress.code.length == 0) return false;
if (_funnelAddress.code.length == 0) {
return false;
}

try IERC5827Proxy(_funnelAddress).baseToken() returns (address baseToken) {
if (baseToken == address(0)) return false;
if (baseToken == address(0)) {
return false;
}
return _funnelAddress == getFunnelForToken(baseToken);
} catch {
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IERC5827.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.15;
pragma solidity 0.8.17;
import "openzeppelin-contracts/interfaces/IERC20.sol";
import "openzeppelin-contracts/interfaces/IERC165.sol";

Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IERC5827Payable.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity 0.8.17;

import "openzeppelin-contracts/interfaces/IERC165.sol";

Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IERC5827Proxy.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.15;
pragma solidity 0.8.17;

interface IERC5827Proxy {
/*
Expand Down
3 changes: 1 addition & 2 deletions src/interfaces/IERC5827Spender.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;
pragma solidity 0.8.17;

/**
* @title IERC5827Spender defines a callback function that is called when renewable allowance is approved
Expand Down
4 changes: 1 addition & 3 deletions src/interfaces/IFunnel.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity 0.8.17;

import { IERC1363 } from "openzeppelin-contracts/interfaces/IERC1363.sol";
import { IERC165 } from "openzeppelin-contracts/interfaces/IERC165.sol";
import { IERC5827 } from "./IERC5827.sol";
import { IERC5827Payable } from "./IERC5827Payable.sol";
import { IERC5827Proxy } from "./IERC5827Proxy.sol";
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IFunnelFactory.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity 0.8.17;

interface IFunnelFactory {
error FunnelNotDeployed();
Expand Down
2 changes: 1 addition & 1 deletion src/lib/NativeMetaTransaction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ abstract contract NativeMetaTransaction is EIP712, Nonces {
0x23d10def3caacba2e4042e0c75d44a42d2558aabcf5ce951d0642a8032e1e653;

event MetaTransactionExecuted(
address userAddress,
address indexed userAddress,
address payable relayerAddress,
zhongfu marked this conversation as resolved.
Show resolved Hide resolved
bytes functionSignature
);
Expand Down
5 changes: 3 additions & 2 deletions src/mocks/MockERC1271.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;


import { IERC1271 } from "openzeppelin-contracts/interfaces/IERC1271.sol";
import { IERC20 } from "openzeppelin-contracts/interfaces/IERC20.sol";
Expand Down
4 changes: 2 additions & 2 deletions src/mocks/MockSpenderReceiver.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { IERC1363Receiver } from "openzeppelin-contracts/interfaces/IERC1363Receiver.sol";
import { IERC5827Spender } from "../interfaces/IERC5827Spender.sol";
Expand Down
4 changes: 2 additions & 2 deletions src/mocks/TestERC20Token.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { ERC20 } from "openzeppelin-contracts/token/ERC20/ERC20.sol";
import { ERC20Permit } from "openzeppelin-contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
Expand Down
4 changes: 2 additions & 2 deletions test/ERC20TestSuite.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { TestSetup } from "./TestSetup.sol";
import { IERC20 } from "openzeppelin-contracts/interfaces/IERC20.sol";
Expand Down
4 changes: 2 additions & 2 deletions test/ERC5827TestSuite.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { TestSetup } from "./TestSetup.sol";
import { IERC5827 } from "../src/interfaces/IERC5827.sol";
Expand Down
4 changes: 2 additions & 2 deletions test/Funnel.t.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import "forge-std/Test.sol";
import { ERC20PresetFixedSupply, ERC20 } from "openzeppelin-contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol";
Expand Down
4 changes: 2 additions & 2 deletions test/FunnelERC20.t.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import "forge-std/Test.sol";
import { ERC20PresetMinterPauser } from "openzeppelin-contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol";
Expand Down
4 changes: 2 additions & 2 deletions test/FunnelFactory.t.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { console } from "forge-std/console.sol";
import "forge-std/Test.sol";
Expand Down
4 changes: 2 additions & 2 deletions test/MockSpenderReceiver.t.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import "forge-std/Test.sol";
import { IERC1363Receiver } from "openzeppelin-contracts/interfaces/IERC1363Receiver.sol";
Expand Down
Loading