Skip to content

Commit

Permalink
[ETHEREUM-CONTRACTS] Add Custom Errors (#1043)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xdavinchee authored Aug 31, 2022
1 parent 5081272 commit 551b96a
Show file tree
Hide file tree
Showing 74 changed files with 6,124 additions and 7,962 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
<a href="https://twitter.com/Superfluid_HQ/status/" target="_blank">
<img alt="Twitter: Superfluid_HQ" src="https://img.shields.io/twitter/follow/Superfluid_HQ.svg?style=social" />
</a>
<a href="https://www.codetriage.com/superfluid-finance/protocol-monorepo">
<img src="https://www.codetriage.com/superfluid-finance/protocol-monorepo/badges/users.svg">
</a>
</p>

> Contracts and resources for the Superfluid Protocol
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
},
"devDependencies": {
"@ethersproject/providers": "^5.6.8",
"@nomicfoundation/hardhat-chai-matchers": "^1.0.3",
"@nomiclabs/hardhat-ethers": "^2.0.6",
"@nomiclabs/hardhat-waffle": "^2.0.3",
"@nomiclabs/hardhat-web3": "^2.0.0",
"@openzeppelin/test-helpers": "^0.5.15",
"@truffle/hdwallet-provider": "^2.0.10",
Expand All @@ -47,7 +47,6 @@
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"ethereum-waffle": "^3.4.4",
"hardhat": "^2.9.9",
"husky": "^8.0.1",
"lerna": "^5.1.6",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity 0.8.14;

import { UUPSProxiable } from "../upgradability/UUPSProxiable.sol";
import { ISuperAgreement } from "../interfaces/superfluid/ISuperAgreement.sol";

import { SuperfluidErrors } from "../interfaces/superfluid/Definitions.sol";

/**
* @title Superfluid agreement base boilerplate contract
Expand All @@ -30,7 +30,7 @@ abstract contract AgreementBase is
function updateCode(address newAddress)
external override
{
require(msg.sender == _host, "only host can update code");
if (msg.sender != _host) revert SuperfluidErrors.ONLY_HOST(SuperfluidErrors.AGREEMENT_BASE_ONLY_HOST);
return _updateCodeAddress(newAddress);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { CallUtils } from "../libs/CallUtils.sol";
* by protocol governance.
*/
contract CFAv1Forwarder {
error CFA_FWD_INVALID_FLOWRATE();
error CFA_FWD_INVALID_FLOW_RATE();

ISuperfluid internal _host;
IConstantFlowAgreementV1 internal _cfa;
Expand Down Expand Up @@ -274,7 +274,7 @@ contract CFAv1Forwarder {
_deleteFlow(token, sender, receiver, new bytes(0));
} // else no change, do nothing
} else {
revert CFA_FWD_INVALID_FLOWRATE();
revert CFA_FWD_INVALID_FLOW_RATE();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity 0.8.14;

import {
IConstantFlowAgreementV1,
SuperfluidErrors,
ISuperfluidToken
} from "../interfaces/agreements/IConstantFlowAgreementV1.sol";
import {
Expand Down Expand Up @@ -123,7 +124,7 @@ contract ConstantFlowAgreementV1 is
internal pure
returns (int96 flowRate)
{
require(deposit <= MAXIMUM_DEPOSIT, "CFA: deposit number too big");
if (deposit > MAXIMUM_DEPOSIT) revert CFA_DEPOSIT_TOO_BIG();
deposit = _clipDepositNumberRoundingDown(deposit);

uint256 flowrate1 = deposit / liquidationPeriod;
Expand All @@ -140,9 +141,10 @@ contract ConstantFlowAgreementV1 is
internal pure
returns (uint256 deposit)
{
require(flowRate > 0, "CFA: not for non-positive flow rate");
require(uint256(int256(flowRate)) * liquidationPeriod <= uint256(int256(type(int96).max)),
"CFA: flow rate too big");
if (flowRate < 0) revert CFA_INVALID_FLOW_RATE();
if (uint256(int256(flowRate)) * liquidationPeriod > uint256(int256(type(int96).max))) {
revert CFA_FLOW_RATE_TOO_BIG();
}
uint256 calculatedDeposit = _calculateDeposit(flowRate, liquidationPeriod);
return AgreementLibrary.max(minimumDeposit, calculatedDeposit);
}
Expand All @@ -165,6 +167,9 @@ contract ConstantFlowAgreementV1 is
external view override
returns (uint256 deposit)
{
// base case: 0 flow rate
if (flowRate == 0) return 0;

ISuperfluid host = ISuperfluid(token.getHost());
ISuperfluidGovernance gov = ISuperfluidGovernance(host.getGovernance());
uint256 minimumDeposit = gov.getConfigAsUint256(host, token, SUPERTOKEN_MINIMUM_DEPOSIT_KEY);
Expand Down Expand Up @@ -402,7 +407,9 @@ contract ConstantFlowAgreementV1 is
internal pure
returns(bytes32 flowId, FlowParams memory flowParams)
{
require(flowVars.receiver != address(0), "CFA: receiver is zero");
if (flowVars.receiver == address(0)) {
revert SuperfluidErrors.ZERO_ADDRESS(SuperfluidErrors.CFA_ZERO_ADDRESS_RECEIVER);
}

flowId = _generateFlowId(flowVars.sender, flowVars.receiver);
flowParams.flowId = flowId;
Expand All @@ -411,8 +418,8 @@ contract ConstantFlowAgreementV1 is
flowParams.flowOperator = currentContext.msgSender;
flowParams.flowRate = flowVars.flowRate;
flowParams.userData = currentContext.userData;
require(flowParams.sender != flowParams.receiver, "CFA: no self flow");
require(flowParams.flowRate > 0, "CFA: invalid flow rate");
if (flowParams.sender == flowParams.receiver) revert CFA_NO_SELF_FLOW();
if (flowParams.flowRate <= 0) revert CFA_INVALID_FLOW_RATE();
}

function _createFlow(
Expand All @@ -426,7 +433,7 @@ contract ConstantFlowAgreementV1 is
(bytes32 flowId, FlowParams memory flowParams) = _createOrUpdateFlowCheck(flowVars, currentContext);

(bool exist, FlowData memory oldFlowData) = _getAgreementData(flowVars.token, flowId);
require(!exist, "CFA: flow already exist");
if (exist) revert SuperfluidErrors.ALREADY_EXISTS(SuperfluidErrors.CFA_FLOW_ALREADY_EXISTS);

if (ISuperfluid(msg.sender).isApp(ISuperApp(flowVars.receiver))) {
newCtx = _changeFlowToApp(
Expand Down Expand Up @@ -454,7 +461,7 @@ contract ConstantFlowAgreementV1 is
{
(, FlowParams memory flowParams) = _createOrUpdateFlowCheck(flowVars, currentContext);

require(exist, "CFA: flow does not exist");
if (!exist) revert SuperfluidErrors.DOES_NOT_EXIST(SuperfluidErrors.CFA_FLOW_DOES_NOT_EXIST);

if (ISuperfluid(msg.sender).isApp(ISuperApp(flowVars.receiver))) {
newCtx = _changeFlowToApp(
Expand All @@ -480,16 +487,20 @@ contract ConstantFlowAgreementV1 is
returns(bytes memory newCtx)
{
FlowParams memory flowParams;
require(flowVars.sender != address(0), "CFA: sender is zero");
require(flowVars.receiver != address(0), "CFA: receiver is zero");
if (flowVars.sender == address(0)) {
revert SuperfluidErrors.ZERO_ADDRESS(SuperfluidErrors.CFA_ZERO_ADDRESS_SENDER);
}
if (flowVars.receiver == address(0)) {
revert SuperfluidErrors.ZERO_ADDRESS(SuperfluidErrors.CFA_ZERO_ADDRESS_RECEIVER);
}
flowParams.flowId = _generateFlowId(flowVars.sender, flowVars.receiver);
flowParams.sender = flowVars.sender;
flowParams.receiver = flowVars.receiver;
flowParams.flowOperator = currentContext.msgSender;
flowParams.flowRate = 0;
flowParams.userData = currentContext.userData;
(bool exist, FlowData memory oldFlowData) = _getAgreementData(flowVars.token, flowParams.flowId);
require(exist, "CFA: flow does not exist");
if (!exist) revert SuperfluidErrors.DOES_NOT_EXIST(SuperfluidErrors.CFA_FLOW_DOES_NOT_EXIST);

(int256 availableBalance,,) = flowVars.token.realtimeBalanceOf(flowVars.sender, currentContext.timestamp);

Expand All @@ -501,7 +512,7 @@ contract ConstantFlowAgreementV1 is
{
if (!ISuperfluid(msg.sender).isAppJailed(ISuperApp(flowVars.sender)) &&
!ISuperfluid(msg.sender).isAppJailed(ISuperApp(flowVars.receiver))) {
require(availableBalance < 0, "CFA: sender account is not critical");
if (availableBalance >= 0) revert CFA_NON_CRITICAL_SENDER();
}
}

Expand Down Expand Up @@ -592,7 +603,7 @@ contract ConstantFlowAgreementV1 is
returns(bytes memory newCtx)
{
ISuperfluid.Context memory currentContext = AgreementLibrary.authorizeTokenAccess(token, ctx);
require(currentContext.msgSender != sender, "CFA: E_NO_SENDER_CREATE");
if (currentContext.msgSender == sender) revert CFA_ACL_NO_SENDER_CREATE();

{
// check if flow operator has create permissions
Expand All @@ -601,16 +612,15 @@ contract ConstantFlowAgreementV1 is
uint8 permissions,
int96 flowRateAllowance
) = getFlowOperatorData(token, sender, currentContext.msgSender);
require(
_getBooleanFlowOperatorPermissions(permissions, FlowChangeType.CREATE_FLOW),
"CFA: E_NO_OPERATOR_CREATE_FLOW"
);
if (!_getBooleanFlowOperatorPermissions(permissions, FlowChangeType.CREATE_FLOW)) {
revert CFA_ACL_OPERATOR_NO_CREATE_PERMISSIONS();
}

// check if desired flow rate is allowed and update flow rate allowance
int96 updatedFlowRateAllowance = flowRateAllowance == type(int96).max
? flowRateAllowance
: flowRateAllowance - flowRate;
require(updatedFlowRateAllowance >= 0, "CFA: E_EXCEED_FLOW_RATE_ALLOWANCE");
if (updatedFlowRateAllowance < 0) revert CFA_ACL_FLOW_RATE_ALLOWANCE_EXCEEDED();
_updateFlowRateAllowance(token, flowOperatorId, permissions, updatedFlowRateAllowance);
}
{
Expand Down Expand Up @@ -639,7 +649,7 @@ contract ConstantFlowAgreementV1 is
returns(bytes memory newCtx)
{
ISuperfluid.Context memory currentContext = AgreementLibrary.authorizeTokenAccess(token, ctx);
require(currentContext.msgSender != sender, "CFA: E_NO_SENDER_UPDATE");
if (currentContext.msgSender == sender) revert CFA_ACL_NO_SENDER_UPDATE();

// check if flow exists
(bool exist, FlowData memory oldFlowData) = _getAgreementData(token, _generateFlowId(sender, receiver));
Expand All @@ -651,16 +661,15 @@ contract ConstantFlowAgreementV1 is
uint8 permissions,
int96 flowRateAllowance
) = getFlowOperatorData(token, sender, currentContext.msgSender);
require(
_getBooleanFlowOperatorPermissions(permissions, FlowChangeType.UPDATE_FLOW),
"E_NO_OPERATOR_UPDATE_FLOW"
);
if (!_getBooleanFlowOperatorPermissions(permissions, FlowChangeType.UPDATE_FLOW)) {
revert CFA_ACL_OPERATOR_NO_UPDATE_PERMISSIONS();
}

// check if desired flow rate is allowed and update flow rate allowance
int96 updatedFlowRateAllowance = flowRateAllowance == type(int96).max || oldFlowData.flowRate >= flowRate
? flowRateAllowance
: flowRateAllowance - (flowRate - oldFlowData.flowRate);
require(updatedFlowRateAllowance >= 0, "CFA: E_EXCEED_FLOW_RATE_ALLOWANCE");
if (updatedFlowRateAllowance < 0) revert CFA_ACL_FLOW_RATE_ALLOWANCE_EXCEEDED();
_updateFlowRateAllowance(token, flowOperatorId, permissions, updatedFlowRateAllowance);
}

Expand Down Expand Up @@ -693,7 +702,7 @@ contract ConstantFlowAgreementV1 is
ISuperfluid.Context memory currentContext = AgreementLibrary.authorizeTokenAccess(token, ctx);
(,uint8 permissions,) = getFlowOperatorData(token, sender, currentContext.msgSender);
bool hasPermissions = _getBooleanFlowOperatorPermissions(permissions, FlowChangeType.DELETE_FLOW);
require(hasPermissions, "E_NO_OPERATOR_DELETE_FLOW");
if (!hasPermissions) revert CFA_ACL_OPERATOR_NO_DELETE_PERMISSIONS();

_StackVars_createOrUpdateFlow memory flowVars;
flowVars.token = token;
Expand All @@ -713,12 +722,12 @@ contract ConstantFlowAgreementV1 is
bytes calldata ctx
) public override returns(bytes memory newCtx) {
newCtx = ctx;
require(FlowOperatorDefinitions.isPermissionsClean(permissions), "CFA: Unclean permissions");
if (!FlowOperatorDefinitions.isPermissionsClean(permissions)) revert CFA_ACL_UNCLEAN_PERMISSIONS();
ISuperfluid.Context memory currentContext = AgreementLibrary.authorizeTokenAccess(token, ctx);
// [SECURITY] NOTE: we are holding the assumption here that ctx is correct and we validate it with
// authorizeTokenAccess:
require(currentContext.msgSender != flowOperator, "CFA: E_NO_SENDER_FLOW_OPERATOR");
require(flowRateAllowance >= 0, "CFA: E_NO_NEGATIVE_ALLOWANCE");
if (currentContext.msgSender == flowOperator) revert CFA_ACL_NO_SENDER_FLOW_OPERATOR();
if (flowRateAllowance < 0) revert CFA_ACL_NO_NEGATIVE_ALLOWANCE();
FlowOperatorData memory flowOperatorData;
flowOperatorData.permissions = permissions;
flowOperatorData.flowRateAllowance = flowRateAllowance;
Expand Down Expand Up @@ -1078,7 +1087,7 @@ contract ConstantFlowAgreementV1 is
userDamageAmount
);
} else {
revert("CFA: APP_RULE_NO_CRITICAL_RECEIVER_ACCOUNT");
revert SuperfluidErrors.APP_RULE(SuperAppDefinitions.APP_RULE_NO_CRITICAL_RECEIVER_ACCOUNT);
}
}
}
Expand Down Expand Up @@ -1220,7 +1229,9 @@ contract ConstantFlowAgreementV1 is
if (currentContext.callType != ContextDefinitions.CALL_INFO_CALL_TYPE_APP_CALLBACK ||
currentContext.appCreditToken != token) {
(int256 availableBalance,,) = token.realtimeBalanceOf(currentContext.msgSender, currentContext.timestamp);
require(availableBalance >= 0, "CFA: not enough available balance");
if (availableBalance < 0) {
revert SuperfluidErrors.INSUFFICIENT_BALANCE(SuperfluidErrors.CFA_INSUFFICIENT_BALANCE);
}
}
}

Expand Down
Loading

0 comments on commit 551b96a

Please sign in to comment.