diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 45d2c63..1b36614 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -28,12 +28,6 @@ contract Circles is ERC1155, ICirclesErrors { // Constants - /** - * @notice Issue one Circle per hour for each human in demurraged units. - * So per second issue 10**18 / 3600 = 277777777777778 attoCircles. - */ - uint256 private constant ISSUANCE_PER_SECOND = uint256(277777777777778); - /** * @notice Upon claiming, the maximum claim is upto two weeks * of history. Unclaimed older Circles are unclaimable. @@ -88,12 +82,16 @@ contract Circles is ERC1155, ICirclesErrors { MintTime memory mintTime = mintTimes[_human]; if (mintTime.mintV1Status != address(0) && mintTime.mintV1Status != CIRCLES_STOPPED_V1) { // Circles v1 contract cannot be active. - revert CirclesERC1155MintBlocked(_human, mintTime.mintV1Status); + // revert CirclesERC1155MintBlocked(_human, mintTime.mintV1Status); + revert CirclesErrorOneAddressArg(_human, 0xC0); } - if (uint256(mintTime.lastMintTime) + 1 hours > block.timestamp) { - // Mint time is set to indefinite future for stopped mints in v2 - // and only complete hours get minted, so shortcut the calculation + // Check if at least one new completed hour is mintable + uint256 lastCompletedHour = mintTime.lastMintTime / 1 hours; + uint256 currentCompletedHour = block.timestamp / 1 hours; + + if (lastCompletedHour >= currentCompletedHour || mintTime.lastMintTime == INDEFINITE_FUTURE) { + // No new completed hour to mint, or stopped return (0, 0, 0); } @@ -112,10 +110,17 @@ contract Circles is ERC1155, ICirclesErrors { // calculate the number of completed hours in day A until `startMint` int128 k = Math64x64.fromUInt((startMint - (dA * 1 days + inflationDayZero)) / 1 hours); - // Calculate the number of incompleted hours remaining in day B from current timestamp - int128 l = Math64x64.fromUInt(((dB + 1) * 1 days + inflationDayZero - block.timestamp) / 1 hours + 1); + // Calculate the number of seconds remaining in the current day (dB) + uint256 secondsRemainingInB = ((dB + 1) * 1 days + inflationDayZero - block.timestamp); + // Calculate the number of complete hours remaining + uint256 hoursRemainingInB = secondsRemainingInB / 1 hours; + // Calculate l: + // If there are any seconds beyond complete hours, add 1 to account for the incomplete hour + // Convert the result to int128 using Math64x64.fromUInt + int128 l = Math64x64.fromUInt(hoursRemainingInB + (secondsRemainingInB % 1 hours > 0 ? 1 : 0)); // calculate the overcounted (demurraged) k (in day A) and l (in day B) hours + // note that the hours l are not demurraged as it is current day by construction int128 overcount = Math64x64.add(Math64x64.mul(R[n], k), l); // subtract the overcount from the total issuance, and convert to attoCircles @@ -138,16 +143,24 @@ contract Circles is ERC1155, ICirclesErrors { // No issuance to claim, simply return without reverting return; } - // mint personal Circles to the human - _mintAndUpdateTotalSupply(_human, toTokenId(_human), issuance, ""); - // update the last mint time + + // update the last mint time, before minting as mint time determines the check (guard for reeentrancy attack) mintTimes[_human].lastMintTime = uint96(block.timestamp); + // mint personal Circles to the human; ERC1155 mint will perform acceptance call + _mintAndUpdateTotalSupply(_human, toTokenId(_human), issuance, "", true); + emit PersonalMint(_human, issuance, startPeriod, endPeriod); } - function _mintAndUpdateTotalSupply(address _account, uint256 _id, uint256 _value, bytes memory _data) internal { - _mint(_account, _id, _value, _data); + function _mintAndUpdateTotalSupply( + address _account, + uint256 _id, + uint256 _value, + bytes memory _data, + bool _doAcceptanceCheck + ) internal { + _mint(_account, _id, _value, _data, _doAcceptanceCheck); uint64 today = day(block.timestamp); DiscountedBalance memory totalSupplyBalance = discountedTotalSupplies[_id]; @@ -155,7 +168,8 @@ contract Circles is ERC1155, ICirclesErrors { _calculateDiscountedBalance(totalSupplyBalance.balance, today - totalSupplyBalance.lastUpdatedDay) + _value; if (newTotalSupply > MAX_VALUE) { // DiscountedBalances: balance exceeds maximum value - revert CirclesDemurrageAmountExceedsMaxUint190(_account, _id, newTotalSupply, 2); + // revert CirclesDemurrageAmountExceedsMaxUint192(_account, _id, newTotalSupply, 2); + revert CirclesErrorAddressUintArgs(_account, _id, 0x80); } totalSupplyBalance.balance = uint192(newTotalSupply); totalSupplyBalance.lastUpdatedDay = today; @@ -176,7 +190,8 @@ contract Circles is ERC1155, ICirclesErrors { // and the total supply might differ on the least significant bits. // There is no good way to handle this, so user should burn a few attoCRC less, // or wait a day for the total supply to be discounted to zero automatically. - revert CirclesLogicAssertion(4); + // revert CirclesLogicAssertion(4); + revert CirclesErrorNoArgs(0x84); } unchecked { totalSupplyBalance.balance = uint192(discountedTotalSupply - _value); @@ -185,14 +200,12 @@ contract Circles is ERC1155, ICirclesErrors { discountedTotalSupplies[_id] = totalSupplyBalance; } - // Private functions - /** * @dev Max function to compare two values. * @param a Value a * @param b Value b */ - function _max(uint256 a, uint256 b) private pure returns (uint256) { + function _max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } } diff --git a/src/circles/Demurrage.sol b/src/circles/Demurrage.sol index 92ed82f..3192ded 100644 --- a/src/circles/Demurrage.sol +++ b/src/circles/Demurrage.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.24; import {ABDKMath64x64 as Math64x64} from "lib/abdk-libraries-solidity/ABDKMath64x64.sol"; import "../errors/Errors.sol"; -contract Demurrage is ICirclesDemurrageErrors { +contract Demurrage is ICirclesCompactErrors, ICirclesDemurrageErrors { // Type declarations /** @@ -256,9 +256,10 @@ contract Demurrage is ICirclesDemurrageErrors { R[_dayDifference] = demurrageFactor; } return demurrageFactor; - } else { - return Math64x64.pow(GAMMA_64x64, _dayDifference); } + // if the day difference is for older than 14 days, calculate the value + // and do not cache it + return Math64x64.pow(GAMMA_64x64, _dayDifference); } /** diff --git a/src/circles/DiscountedBalances.sol b/src/circles/DiscountedBalances.sol index 5e81805..418535c 100644 --- a/src/circles/DiscountedBalances.sol +++ b/src/circles/DiscountedBalances.sol @@ -46,7 +46,8 @@ contract DiscountedBalances is Demurrage { DiscountedBalance memory discountedBalance = discountedBalances[_id][_account]; if (_day < discountedBalance.lastUpdatedDay) { // DiscountedBalances: day is before last updated day - revert CirclesDemurrageDayBeforeLastUpdatedDay(_account, _id, _day, discountedBalance.lastUpdatedDay, 0); + // revert CirclesDemurrageDayBeforeLastUpdatedDay(_account, _id, _day, discountedBalance.lastUpdatedDay, 0); + revert CirclesErrorAddressUintArgs(_account, discountedBalance.lastUpdatedDay, 0xA0); } uint256 dayDifference; unchecked { @@ -93,7 +94,8 @@ contract DiscountedBalances is Demurrage { function _updateBalance(address _account, uint256 _id, uint256 _balance, uint64 _day) internal { if (_balance > MAX_VALUE) { // DiscountedBalances: balance exceeds maximum value - revert CirclesDemurrageAmountExceedsMaxUint190(_account, _id, _balance, 0); + // revert CirclesDemurrageAmountExceedsMaxUint192(_account, _id, _balance, 0); + revert CirclesErrorAddressUintArgs(_account, _id, 0x81); } DiscountedBalance memory discountedBalance = discountedBalances[_id][_account]; discountedBalance.balance = uint192(_balance); @@ -112,7 +114,8 @@ contract DiscountedBalances is Demurrage { DiscountedBalance memory discountedBalance = discountedBalances[_id][_account]; if (_day < discountedBalance.lastUpdatedDay) { // DiscountedBalances: day is before last updated day - revert CirclesDemurrageDayBeforeLastUpdatedDay(_account, _id, _day, discountedBalance.lastUpdatedDay, 1); + // revert CirclesDemurrageDayBeforeLastUpdatedDay(_account, _id, _day, discountedBalance.lastUpdatedDay, 1); + revert CirclesErrorAddressUintArgs(_account, discountedBalance.lastUpdatedDay, 0xA1); } uint256 dayDifference; unchecked { @@ -129,7 +132,8 @@ contract DiscountedBalances is Demurrage { uint256 updatedBalance = discountedBalanceOnDay + _value; if (updatedBalance > MAX_VALUE) { // DiscountedBalances: balance exceeds maximum value - revert CirclesDemurrageAmountExceedsMaxUint190(_account, _id, updatedBalance, 1); + // revert CirclesDemurrageAmountExceedsMaxUint190(_account, _id, updatedBalance, 1); + revert CirclesErrorAddressUintArgs(_account, _id, 0x82); } discountedBalance.balance = uint192(updatedBalance); discountedBalance.lastUpdatedDay = _day; diff --git a/src/circles/ERC1155.sol b/src/circles/ERC1155.sol index 8ad5f21..23f2a30 100644 --- a/src/circles/ERC1155.sol +++ b/src/circles/ERC1155.sol @@ -318,15 +318,20 @@ abstract contract ERC1155 is DiscountedBalances, Context, ERC165, IERC1155, IERC * Requirements: * * - `to` cannot be the zero address. + * - If `_doAcceptanceCheck` is true, it will perform ERC1155 acceptance check, otherwise only update * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ - function _mint(address to, uint256 id, uint256 value, bytes memory data) internal { + function _mint(address to, uint256 id, uint256 value, bytes memory data, bool _doAcceptanceCheck) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); - _updateWithAcceptanceCheck(address(0), to, ids, values, data); + if (_doAcceptanceCheck) { + _updateWithAcceptanceCheck(address(0), to, ids, values, data); + } else { + _update(address(0), to, ids, values); + } } /** diff --git a/src/circles/InflationaryOperator.sol b/src/circles/InflationaryOperator.sol index 1105940..20f542b 100644 --- a/src/circles/InflationaryOperator.sol +++ b/src/circles/InflationaryOperator.sol @@ -27,6 +27,8 @@ contract InflationaryCirclesOperator is BatchedDemurrage { constructor(IHubV2 _hub) { hub = _hub; + // read inflation day zero from hub + inflationDayZero = hub.inflationDayZero(); } // Public functions diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 155d4d0..ce5ef4c 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -1,72 +1,159 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.24; +// Explainer on error codes: 3 leading bits for the error type, 5 bits for the error code. +// +------------+-------------------+-------------+ +// | Error Type | Hex Code Range | Occurances | +// +------------+-------------------+-------------+ +// | 0 | 0x00 to 0x1F | 32 | +// | 1 | 0x20 to 0x3F | 32 | +// | 2 | 0x40 to 0x5F | 32 | +// | 3 | 0x60 to 0x7F | 32 | +// | 4 | 0x80 to 0x9F | 32 | +// | 5 | 0xA0 to 0xBF | 32 | +// | 6 | 0xC0 to 0xDF | 32 | +// | 7 | 0xE0 to 0xFF | 32 | +// +------------+-------------------+-------------+ +// +// for convenience a reference table for the 32 occurances hex conversions; +// so you can "add" the error type easily +// +------------+------------+------------+------------+------------+------------+------------+------------+ +// | Occurrence | Hex Code | Occurrence | Hex Code | Occurrence | Hex Code | Occurrence | Hex Code | +// +------------+------------+------------+------------+------------+------------+------------+------------+ +// | 0 | 0x00 | 1 | 0x01 | 2 | 0x02 | 3 | 0x03 | +// | 4 | 0x04 | 5 | 0x05 | 6 | 0x06 | 7 | 0x07 | +// | 8 | 0x08 | 9 | 0x09 | 10 | 0x0A | 11 | 0x0B | +// | 12 | 0x0C | 13 | 0x0D | 14 | 0x0E | 15 | 0x0F | +// | 16 | 0x10 | 17 | 0x11 | 18 | 0x12 | 19 | 0x13 | +// | 20 | 0x14 | 21 | 0x15 | 22 | 0x16 | 23 | 0x17 | +// | 24 | 0x18 | 25 | 0x19 | 26 | 0x1A | 27 | 0x1B | +// | 28 | 0x1C | 29 | 0x1D | 30 | 0x1E | 31 | 0x1F | +// +------------+------------+------------+------------+------------+------------+------------+------------+ + +interface ICirclesCompactErrors { + /** + * @dev CirclesErrorNoArgs is a generic error that does not require any arguments. + * error type: + * 0: 0x00 -> 0x1F CirclesAddressCannotBeZero + * 1: 0x20 -> 0x3F CirclesArrayMustNotBeEmpty (no occurances anymore; freed up) + * 2: 0x40 -> 0x5F CirclesAmountMustNotBeZero + * 3: 0x60 -> 0x7F CirclesHubFlowVerticesMustBeSorted + * 4: 0x80 -> 0x9F CirclesLogicAssertion + * 5: 0xA0 -> 0xBF CirclesArraysLengthMismatch + */ + error CirclesErrorNoArgs(uint8); + + /** + * @dev CirclesErrorOneAddressArg is a generic error that requires one address argument. + * error type: + * 0: 0x00 -> 0x1F CirclesHubMustBeHuman(avatar) + * 1: 0x20 -> 0x3F CirclesAvatarMustBeRegistered(avatar) + * 2: 0x40 -> 0x5F CirclesHubGroupIsNotRegistered(group) + * 3: 0x60 -> 0x7F CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(avatar) + * 4: 0x80 -> 0x9F CirclesHubAvatarAlreadyRegistered(avatar) + * 5: 0xA0 -> 0xBF CirclesHubInvalidTrustReceiver(trustReceiver) + * 6: 0xC0 -> 0xDF CirclesERC1155MintBlocked(human, ~mintV1Status~) + * 7: 0xE0 -> 0xFF CirclesInvalidFunctionCaller(caller) + */ + error CirclesErrorOneAddressArg(address, uint8); + + /** + * @dev CirclesErrorAddressUintArgs is a generic error that provides an address and a uint256 as arguments. + * error type: + * 0: 0x00 -> 0x1F CirclesHubOperatorNotApprovedForSource(source, streamIndex) + * 1: 0x20 -> 0x3F CirclesHubFlowEdgeIsNotPermitted(receiver, circlesId) + * 2: 0x40 -> 0x5F CirclesHubGroupMintPolicyRejectedBurn(burner, toTokenId(group)) + * 3: 0x60 -> 0x7F CirclesHubGroupMintPolicyRejectedMint(minter, toTokenId) + * 4: 0x80 -> 0x9F CirclesDemurrageAmountExceedsMaxUint192(account, circlesId) + * 5: 0xA0 -> 0xBF CirclesDemurrageDayBeforeLastUpdatedDay(account, lastDayUpdated) + */ + error CirclesErrorAddressUintArgs(address, uint256, uint8); +} + interface IHubErrors { - error CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(address avatar, uint8 code); + // CirclesErrorOneAddressArg 3 + // error CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(address avatar, uint8 code); - error CirclesHubAvatarAlreadyRegistered(address avatar, uint8 code); + // CirclesErrorOneAddressArg 4 + // error CirclesHubAvatarAlreadyRegistered(address avatar, uint8 code); - error CirclesHubMustBeHuman(address avatar, uint8 code); + // CirclesErrorOneAddressArg 0 + // error CirclesHubMustBeHuman(address avatar, uint8 code); - error CirclesHubGroupIsNotRegistered(address group, uint8 code); + // CirclesErrorOneAddressArg 2 + // error CirclesHubGroupIsNotRegistered(address group, uint8 code); - error CirclesHubInvalidTrustReceiver(address trustReceiver, uint8 code); + // CirclesErrorOneAddressArg 5 + // error CirclesHubInvalidTrustReceiver(address trustReceiver, uint8 code); - error CirclesHubGroupMintPolicyRejectedMint( - address minter, address group, uint256[] collateral, uint256[] amounts, bytes data, uint8 code - ); + // CirclesErrorAddressUintArgs 3 + // error CirclesHubGroupMintPolicyRejectedMint( + // address minter, address group, uint256[] collateral, uint256[] amounts, bytes data, uint8 code + // ); - error CirclesHubGroupMintPolicyRejectedBurn(address burner, address group, uint256 amount, bytes data, uint8 code); + // CirclesErrorAddressUintArgs 2 + // error CirclesHubGroupMintPolicyRejectedBurn(address burner, address group, uint256 amount, bytes data, uint8 code); - error CirclesHubOperatorNotApprovedForSource(address operator, address source, uint16 streamId, uint8 code); + // CirclesErrorAddressUintArgs 0 + // error CirclesHubOperatorNotApprovedForSource(address operator, address source, uint16 streamIndex, uint8 code); - error CirclesHubFlowEdgeIsNotPermitted(address receiver, uint256 circlesId, uint8 code); + // CirclesErrorAddressUintArgs 1 + // error CirclesHubFlowEdgeIsNotPermitted(address receiver, uint256 circlesId, uint8 code); - error CirclesHubFlowVerticesMustBeSorted(); + // CirclesErrorNoArgs 3 + // error CirclesHubFlowVerticesMustBeSorted(); error CirclesHubFlowEdgeStreamMismatch(uint16 flowEdgeId, uint16 streamId, uint8 code); - error CirclesHubStreamMismatch(uint16 streamId, uint8 code); + error CirclesHubStreamMismatch(uint16 streamId); error CirclesHubNettedFlowMismatch(uint16 vertexPosition, int256 matrixNettedFlow, int256 streamNettedFlow); } interface ICirclesDemurrageErrors { - error CirclesERC1155MintBlocked(address human, address mintV1Status); + // CirclesErrorOneAddressArg 6 + // error CirclesERC1155MintBlocked(address human, address mintV1Status); - error CirclesDemurrageAmountExceedsMaxUint190(address account, uint256 circlesId, uint256 amount, uint8 code); + // CirclesErrorAddressUintArgs 4 + // error CirclesDemurrageAmountExceedsMaxUint192(address account, uint256 circlesId, uint256 amount, uint8 code); - error CirclesDemurrageDayBeforeLastUpdatedDay( - address account, uint256 circlesId, uint64 day, uint64 lastUpdatedDay, uint8 code - ); + // CirclesErrorAddressUintArgs 5 + // error CirclesDemurrageDayBeforeLastUpdatedDay( + // address account, uint256 circlesId, uint64 day, uint64 lastUpdatedDay, uint8 code + // ); error CirclesERC1155CannotReceiveBatch(uint8 code); } interface ICirclesErrors { - error CirclesAvatarMustBeRegistered(address avatar, uint8 code); + // CirclesErrorOneAddressArg 1 + // error CirclesAvatarMustBeRegistered(address avatar, uint8 code); - error CirclesAddressCannotBeZero(uint8 code); + // CirclesErrorNoArgs 0 + // error CirclesAddressCannotBeZero(uint8 code); - error CirclesInvalidFunctionCaller(address caller, address expectedCaller, uint8 code); + // CirclesErrorOneAddressArg + // error CirclesInvalidFunctionCaller(address caller, address expectedCaller, uint8 code); error CirclesInvalidCirclesId(uint256 id, uint8 code); - error CirclesInvalidString(string str, uint8 code); - error CirclesInvalidParameter(uint256 parameter, uint8 code); error CirclesAmountOverflow(uint256 amount, uint8 code); - error CirclesArraysLengthMismatch(uint256 lengthArray1, uint256 lengthArray2, uint8 code); + // CirclesErrorNoArgs 5 + // error CirclesArraysLengthMismatch(uint256 lengthArray1, uint256 lengthArray2, uint8 code); - error CirclesArrayMustNotBeEmpty(uint8 code); + // CirclesErrorNoArgs 1 + // error CirclesArrayMustNotBeEmpty(uint8 code); - error CirclesAmountMustNotBeZero(uint8 code); + // CirclesErrorNoArgs 2 + // error CirclesAmountMustNotBeZero(uint8 code); error CirclesProxyAlreadyInitialized(); - error CirclesLogicAssertion(uint8 code); + // CirclesErrorNoArgs 4 + // error CirclesLogicAssertion(uint8 code); error CirclesIdMustBeDerivedFromAddress(uint256 providedId, uint8 code); @@ -95,4 +182,10 @@ interface INameRegistryErrors { error CirclesNamesAvatarAlreadyHasCustomNameOrSymbol(address avatar, string nameOrSymbol, uint8 code); error CirclesNamesOrganizationHasNoSymbol(address organization, uint8 code); + + error CirclesNamesShortNameZero(address avatar, uint256 nonce); +} + +interface IMigrationErrors { + error CirclesMigrationAmountMustBeGreaterThanZero(); } diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index b99a4a9..de93498 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -25,12 +25,12 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // Constants /** - * @dev Welcome bonus for new avatars invited to Circles. Set to 50 Circles. + * @dev Welcome bonus for new avatars invited to Circles. Set to 48 Circles. */ uint256 private constant WELCOME_BONUS = 48 * EXA; /** - * @dev The cost of an invitation for a new avatar, paid in personal Circles burnt, set to 100 Circles. + * @dev The cost of an invitation for a new avatar, paid in personal Circles burnt, set to 96 Circles. */ uint256 private constant INVITATION_COST = 2 * WELCOME_BONUS; @@ -127,6 +127,10 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); + event GroupMint( + address indexed sender, address indexed receiver, address indexed group, uint256[] collateral, uint256[] amounts + ); + // Modifiers /** @@ -134,7 +138,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { */ modifier onlyMigration() { if (msg.sender != migration) { - revert CirclesInvalidFunctionCaller(msg.sender, migration, 0); + // revert CirclesInvalidFunctionCaller(msg.sender, migration, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0xE0); } _; } @@ -143,7 +148,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * @dev Reentrancy guard for nonReentrant functions. * see https://soliditylang.org/blog/2024/01/26/transient-storage/ */ - modifier nonReentrant(uint8 _code) { + modifier nonReentrant() { assembly { if tload(0) { revert(0, 0) } tstore(0, 1) @@ -178,10 +183,12 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { string memory _gatewayUrl ) Circles(_inflationDayZero, _gatewayUrl) { if (address(_hubV1) == address(0)) { - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x00); } if (_standardTreasury == address(0)) { - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x01); } // initialize linked list for avatars @@ -230,23 +237,19 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // only available for v1 users with stopped v1 mint, for initial bootstrap period (address v1CirclesStatus, uint256 v1LastTouched) = _registerHuman(msg.sender); // check if v1 Circles exists and has been stopped - if (v1CirclesStatus != CIRCLES_STOPPED_V1) { - revert CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(msg.sender, 0); - } - // if it has been stopped, did it stop before the end of the invitation period? - if (v1LastTouched >= invitationOnlyTime) { - revert CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(msg.sender, 1); + // and if it has been stopped, did it stop before the end of the invitation period? + if (v1CirclesStatus != CIRCLES_STOPPED_V1 || v1LastTouched >= invitationOnlyTime) { + // revert CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(msg.sender, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0x60); } } else { // if someone has invited you by trusting your address ahead of this call, // they must themselves be a registered human, and they must pay the invitation cost (after invitation period). - if (!isHuman(_inviter)) { - revert CirclesHubMustBeHuman(msg.sender, 0); - } - - if (!isTrusted(_inviter, msg.sender)) { - revert CirclesHubInvalidTrustReceiver(msg.sender, 0); + if (!isHuman(_inviter) || !isTrusted(_inviter, msg.sender)) { + // revert CirclesHubMustBeHuman(msg.sender, 0); + // revert CirclesHubInvalidTrustReceiver(msg.sender, 0); + revert CirclesErrorOneAddressArg(_inviter, 0xA0); } // register the invited human; reverts if they already exist @@ -260,7 +263,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { _burnAndUpdateTotalSupply(_inviter, toTokenId(_inviter), INVITATION_COST); // mint the welcome bonus to the newly registered human - _mintAndUpdateTotalSupply(msg.sender, toTokenId(msg.sender), WELCOME_BONUS, ""); + _mintAndUpdateTotalSupply(msg.sender, toTokenId(msg.sender), WELCOME_BONUS, "", true); } } @@ -346,18 +349,17 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * The trusted address does not (yet) have to be registered in the Hub contract. */ function trust(address _trustReceiver, uint96 _expiry) external { - if (avatars[msg.sender] == address(0)) { - revert CirclesAvatarMustBeRegistered(msg.sender, 0); - } - if (_trustReceiver == address(0) || _trustReceiver == SENTINEL) { + if ( + avatars[msg.sender] == address(0) || _trustReceiver == address(0) || _trustReceiver == SENTINEL + || _trustReceiver == msg.sender + ) { // You cannot trust the zero address or the sentinel address. // Reserved addresses for logic. - revert CirclesHubInvalidTrustReceiver(_trustReceiver, 1); - } - if (_trustReceiver == msg.sender) { - // You cannot edit your own trust relation. - revert CirclesHubInvalidTrustReceiver(_trustReceiver, 2); + // You also cannot edit your own trust relation. + // revert CirclesHubInvalidTrustReceiver(_trustReceiver, 1); + revert CirclesErrorOneAddressArg(_trustReceiver, 0xA1); } + // expiring trust cannot be set in the past if (_expiry < block.timestamp) _expiry = uint96(block.timestamp); _trust(msg.sender, _trustReceiver, _expiry); @@ -369,7 +371,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function personalMint() external { if (!isHuman(msg.sender)) { // Only avatars registered as human can call personal mint. - revert CirclesHubMustBeHuman(msg.sender, 1); + // revert CirclesHubMustBeHuman(msg.sender, 1); + revert CirclesErrorOneAddressArg(msg.sender, 0x01); } // check if v1 Circles is known to be stopped and update status _checkHumanV1CirclesStatus(msg.sender); @@ -436,7 +439,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function stop() external { if (!isHuman(msg.sender)) { // Only human can call stop. - revert CirclesHubMustBeHuman(msg.sender, 2); + // revert CirclesHubMustBeHuman(msg.sender, 2); + revert CirclesErrorOneAddressArg(msg.sender, 0x02); } MintTime storage mintTime = mintTimes[msg.sender]; // check if already stopped @@ -457,7 +461,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function stopped(address _human) external view returns (bool) { if (!isHuman(_human)) { // Only personal Circles can have a status of boolean stopped. - revert CirclesHubMustBeHuman(_human, 3); + // revert CirclesHubMustBeHuman(_human, 3); + revert CirclesErrorOneAddressArg(_human, 0x03); } MintTime storage mintTime = mintTimes[msg.sender]; return (mintTime.lastMintTime == INDEFINITE_FUTURE); @@ -475,12 +480,12 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * @param _amounts array of amounts in inflationary v1 units to migrate */ function migrate(address _owner, address[] calldata _avatars, uint256[] calldata _amounts) external onlyMigration { - if (avatars[_owner] == address(0)) { + if (avatars[_owner] == address(0) || _avatars.length != _amounts.length) { // Only registered avatars can migrate v1 tokens. - revert CirclesAvatarMustBeRegistered(_owner, 1); - } - if (_avatars.length != _amounts.length) { - revert CirclesArraysLengthMismatch(_avatars.length, _amounts.length, 0); + // Array length is already checked in the migration contract, so redundant check here, + // can be collapsed under the more meaningful error. + // revert CirclesAvatarMustBeRegistered(_owner, 1); + revert CirclesErrorOneAddressArg(_owner, 0x21); } // register all unregistered avatars as humans, and check that registered avatars are humans @@ -492,14 +497,15 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // personal Circles are required to burn the invitation cost if (!isHuman(_owner)) { // Only humans can migrate v1 tokens after the bootstrap period. - revert CirclesHubMustBeHuman(_owner, 4); + // revert CirclesHubMustBeHuman(_owner, 4); + revert CirclesErrorOneAddressArg(_owner, 0x04); } _burnAndUpdateTotalSupply(_owner, toTokenId(_owner), cost); } for (uint256 i = 0; i < _avatars.length; i++) { // mint the migrated balances to _owner - _mintAndUpdateTotalSupply(_owner, toTokenId(_avatars[i]), _amounts[i], ""); + _mintAndUpdateTotalSupply(_owner, toTokenId(_avatars[i]), _amounts[i], "", true); } } @@ -521,7 +527,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // then the mint policy must approve the burn if (!policy.beforeBurnPolicy(msg.sender, group, _amount, _data)) { // Burn policy rejected burn. - revert CirclesHubGroupMintPolicyRejectedBurn(msg.sender, group, _amount, _data, 0); + // revert CirclesHubGroupMintPolicyRejectedBurn(msg.sender, group, _amount, _data, 0); + revert CirclesErrorAddressUintArgs(msg.sender, _id, 0x40); } } _burnAndUpdateTotalSupply(msg.sender, _id, _amount); @@ -530,7 +537,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function wrap(address _avatar, uint256 _amount, CirclesType _type) external returns (address) { if (!isHuman(_avatar) && !isGroup(_avatar)) { // Avatar must be human or group. - revert CirclesAvatarMustBeRegistered(_avatar, 2); + // revert CirclesAvatarMustBeRegistered(_avatar, 2); + revert CirclesErrorOneAddressArg(_avatar, 0x22); } address erc20Wrapper = liftERC20.ensureERC20(_avatar, _type); safeTransferFrom(msg.sender, erc20Wrapper, toTokenId(_avatar), _amount, ""); @@ -543,7 +551,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { FlowEdge[] calldata _flow, Stream[] calldata _streams, bytes calldata _packedCoordinates - ) external nonReentrant(0) { + ) external nonReentrant { // first unpack the coordinates to array of uint16 uint16[] memory coordinates = _unpackCoordinates(_packedCoordinates, _flow.length); @@ -551,9 +559,10 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { for (uint16 i = 0; i < _streams.length; i++) { if (!isApprovedForAll(_flowVertices[_streams[i].sourceCoordinate], msg.sender)) { // Operator not approved for source. - revert CirclesHubOperatorNotApprovedForSource( - msg.sender, _flowVertices[_streams[i].sourceCoordinate], i, 0 - ); + // revert CirclesHubOperatorNotApprovedForSource( + // msg.sender, _flowVertices[_streams[i].sourceCoordinate], i, 0 + // ); + revert CirclesErrorAddressUintArgs(_flowVertices[_streams[i].sourceCoordinate], i, 0x00); } } @@ -580,7 +589,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function setAdvancedUsageFlag(bytes32 _flag) external { if (avatars[msg.sender] == address(0)) { // Only registered avatars can set advanced usage flags. - revert CirclesAvatarMustBeRegistered(msg.sender, 3); + // revert CirclesAvatarMustBeRegistered(msg.sender, 3); + revert CirclesErrorOneAddressArg(msg.sender, 0x23); } advancedUsageFlags[msg.sender] = _flag; @@ -673,17 +683,16 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { bytes memory _data, bool _explicitCall ) internal { - if (_collateral.length != _amounts.length) { + if (_collateral.length != _amounts.length || _collateral.length == 0) { // Collateral and amount arrays must have equal length. - revert CirclesArraysLengthMismatch(_collateral.length, _amounts.length, 1); - } - if (_collateral.length == 0) { // At least one collateral must be provided. - revert CirclesArrayMustNotBeEmpty(0); + // revert CirclesArraysLengthMismatch(_collateral.length, _amounts.length, 1); + revert CirclesErrorNoArgs(0xA1); } if (!isGroup(_group)) { // Group is not registered as an avatar. - revert CirclesHubGroupIsNotRegistered(_group, 0); + // revert CirclesHubGroupIsNotRegistered(_group, 0); + revert CirclesErrorOneAddressArg(_group, 0x40); } // note: we don't need to check whether collateral circle ids are registered, @@ -698,22 +707,21 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { bool isValidCollateral = _explicitCall ? isTrusted(_group, collateralAvatar) : isPermittedFlow(_sender, _group, collateralAvatar); - if (!isValidCollateral) { + if (!isValidCollateral || _amounts[i] == 0) { // Group does not trust collateral, or flow edge is not permitted - revert CirclesHubFlowEdgeIsNotPermitted(_group, _collateral[i], 0); - } - - if (_amounts[i] == 0) { // Non-zero collateral must be provided. - revert CirclesAmountMustNotBeZero(0); + // revert CirclesHubFlowEdgeIsNotPermitted(_group, _collateral[i], 0); + revert CirclesErrorAddressUintArgs(_group, _collateral[i], 0x20); } + sumAmounts += _amounts[i]; } // Rely on the mint policy to determine whether the collateral is valid for minting if (!IMintPolicy(mintPolicies[_group]).beforeMintPolicy(_sender, _group, _collateral, _amounts, _data)) { // Mint policy rejected mint. - revert CirclesHubGroupMintPolicyRejectedMint(_sender, _group, _collateral, _amounts, _data, 0); + // revert CirclesHubGroupMintPolicyRejectedMint(_sender, _group, _collateral, _amounts, _data, 0); + revert CirclesErrorAddressUintArgs(_sender, toTokenId(_group), 0x60); } // abi encode the group address into the data to send onwards to the treasury @@ -725,8 +733,13 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // note: treasury.on1155Received must implement and unpack the GroupMintMetadata to know the group safeBatchTransferFrom(_sender, treasuries[_group], _collateral, _amounts, dataWithGroup); - // mint group Circles to the receiver and send the original _data onwards - _mintAndUpdateTotalSupply(_receiver, toTokenId(_group), sumAmounts, _data); + // mint group Circles to the receiver and send the original _data onwards. + // Only if it is an explicit call perform the ERC1155 acceptance call; if not (ie via path), + // suppress the normal acceptance call and only perform the final stream based acceptance calls + _mintAndUpdateTotalSupply(_receiver, toTokenId(_group), sumAmounts, _data, _explicitCall); + + // emit the group mint event + emit GroupMint(_sender, _receiver, _group, _collateral, _amounts); } /** @@ -743,17 +756,13 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { FlowEdge[] calldata _flow, uint16[] memory _coordinates ) internal view returns (int256[] memory) { - if (3 * _flow.length != _coordinates.length) { - // Mismatch in flow and coordinates length. - revert CirclesArraysLengthMismatch(_flow.length, _coordinates.length, 2); - } - if (_flowVertices.length > type(uint16).max) { - // Too many vertices. - revert CirclesArraysLengthMismatch(_flowVertices.length, type(uint16).max, 3); - } - if (_flowVertices.length == 0 || _flow.length == 0) { - // Empty flow matrix - revert CirclesArraysLengthMismatch(_flowVertices.length, _flow.length, 4); + if ( + 3 * _flow.length != _coordinates.length // Mismatch in flow and coordinates length. + || _flowVertices.length > type(uint16).max // Too many vertices. + || _flowVertices.length == 0 || _flow.length == 0 // Empty flow matrix + ) { + // revert CirclesArraysLengthMismatch(_flow.length, _coordinates.length, 2); + revert CirclesErrorNoArgs(0xA2); } // initialize the netted flow array @@ -764,18 +773,21 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { for (uint64 i = 0; i < _flowVertices.length - 1; i++) { if (uint160(_flowVertices[i]) >= uint160(_flowVertices[i + 1])) { // Flow vertices must be in ascending order. - revert CirclesHubFlowVerticesMustBeSorted(); + // revert CirclesHubFlowVerticesMustBeSorted(); + revert CirclesErrorNoArgs(0x60); } if (avatars[_flowVertices[i]] == address(0)) { // Avatar must be registered. - revert CirclesAvatarMustBeRegistered(_flowVertices[i], 4); + // revert CirclesAvatarMustBeRegistered(_flowVertices[i], 4); + revert CirclesErrorOneAddressArg(_flowVertices[i], 0x24); } } address lastAvatar = _flowVertices[_flowVertices.length - 1]; if (avatars[lastAvatar] == address(0)) { // Avatar must be registered. - revert CirclesAvatarMustBeRegistered(lastAvatar, 5); + // revert CirclesAvatarMustBeRegistered(lastAvatar, 5); + revert CirclesErrorOneAddressArg(lastAvatar, 0x25); } } @@ -796,7 +808,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // and if the sender has enabled consented flow, also check that the sender trusts the receiver if (!isPermittedFlow(from, to, circlesId)) { // Flow edge is not permitted. - revert CirclesHubFlowEdgeIsNotPermitted(to, toTokenId(circlesId), 1); + // revert CirclesHubFlowEdgeIsNotPermitted(to, toTokenId(circlesId), 1); + revert CirclesErrorAddressUintArgs(to, toTokenId(circlesId), 0x21); } // nett the flow, dividing out the different Circle identifiers @@ -853,11 +866,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { streamBatchCounter[streamSinkArrayId]++; if (streamReceivers[streamSinkArrayId] == address(0)) { streamReceivers[streamSinkArrayId] = to; - } else { - if (streamReceivers[streamSinkArrayId] != to) { - // Invalid stream receiver - revert CirclesHubFlowEdgeStreamMismatch(i, _flow[i].streamSinkId, 1); - } + } else if (streamReceivers[streamSinkArrayId] != to) { + // Invalid stream receiver + revert CirclesHubFlowEdgeStreamMismatch(i, _flow[i].streamSinkId, 1); } } @@ -889,13 +900,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // check that all streams are properly defined for (uint16 i = 0; i < _streams.length; i++) { - if (streamReceivers[i] == address(0)) { + if (streamReceivers[i] == address(0) || streamBatchCounter[i] != _streams[i].flowEdgeIds.length) { // Invalid stream receiver - revert CirclesHubStreamMismatch(i, 0); - } - if (streamBatchCounter[i] != _streams[i].flowEdgeIds.length) { - // Invalid stream batch - revert CirclesHubStreamMismatch(i, 1); + revert CirclesHubStreamMismatch(i); } } } @@ -954,12 +961,13 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function _matchNettedFlows(int256[] memory _streamsNettedFlow, int256[] memory _matrixNettedFlow) internal pure { if (_streamsNettedFlow.length != _matrixNettedFlow.length) { // Mismatch in netted flow length. - revert CirclesArraysLengthMismatch(_streamsNettedFlow.length, _matrixNettedFlow.length, 5); + // revert CirclesArraysLengthMismatch(_streamsNettedFlow.length, _matrixNettedFlow.length, 5); + revert CirclesErrorNoArgs(0xA5); } for (uint16 i = 0; i < _streamsNettedFlow.length; i++) { if (_streamsNettedFlow[i] != _matrixNettedFlow[i]) { // Intended flow does not match verified flow. - revert CirclesHubNettedFlowMismatch(i, _streamsNettedFlow[i], _matrixNettedFlow[i]); + revert CirclesHubNettedFlowMismatch(i, _matrixNettedFlow[i], _streamsNettedFlow[i]); } } } @@ -1004,25 +1012,15 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { string calldata _name, string calldata _symbol ) internal { - // todo: we could check ERC165 support interface for mint policy - if (_mint == address(0)) { + if (_mint == address(0) || _treasury == address(0)) { // Mint address can not be zero. - revert CirclesAddressCannotBeZero(2); - } - // todo: same check treasury is an ERC1155Receiver for receiving collateral - if (_treasury == address(0)) { // Treasury address can not be zero. - revert CirclesAddressCannotBeZero(3); + revert CirclesErrorNoArgs(0x02); } - if (!nameRegistry.isValidName(_name)) { - // Invalid group name. + if (!nameRegistry.isValidName(_name) || !nameRegistry.isValidSymbol(_symbol)) { + // Invalid group name or symbol // name must be ASCII alphanumeric and some special characters - revert CirclesInvalidString(_name, 0); - } - if (!nameRegistry.isValidSymbol(_symbol)) { - // Invalid group symbol. - // symbol must be ASCII alphanumeric and some special characters - revert CirclesInvalidString(_symbol, 1); + revert CirclesErrorNoArgs(0x03); } // insert avatar into linked list; reverts if it already exists @@ -1050,7 +1048,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } else { if (!isHuman(_avatars[i])) { // Only humans can be registered. - revert CirclesHubMustBeHuman(_avatars[i], 5); + // revert CirclesHubMustBeHuman(_avatars[i], 5); + revert CirclesErrorOneAddressArg(_avatars[i], 0x05); } } } @@ -1111,13 +1110,16 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // as this marks whether an avatar is registered as human or not if (mintTime.lastMintTime == 0) { // Avatar must already be registered as human before we call update - revert CirclesLogicAssertion(0); + // revert CirclesLogicAssertion(0); + revert CirclesErrorNoArgs(0x80); } // if the status has changed, update the last mint time // to avoid possible overlap of the mint between Hub v1 and Hub v2 if (mintTime.mintV1Status != _mintV1Status) { mintTime.mintV1Status = _mintV1Status; - mintTime.lastMintTime = uint96(block.timestamp); + // for last mint time take the maximum to avoid resetting "INDEFINITE_FUTURE" + // which indicates stopped status of the human + mintTime.lastMintTime = uint96(_max(mintTime.lastMintTime, uint96(block.timestamp))); } } @@ -1129,7 +1131,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function _insertAvatar(address _avatar) internal { if (avatars[_avatar] != address(0)) { // Avatar already inserted - revert CirclesHubAvatarAlreadyRegistered(_avatar, 0); + // revert CirclesHubAvatarAlreadyRegistered(_avatar, 0); + revert CirclesErrorOneAddressArg(_avatar, 0x80); } avatars[_avatar] = avatars[SENTINEL]; avatars[SENTINEL] = _avatar; @@ -1159,7 +1162,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { { if (_packedData.length != _numberOfTriplets * 6) { // Invalid packed data length - revert CirclesArraysLengthMismatch(_packedData.length, _numberOfTriplets, 6); + // revert CirclesArraysLengthMismatch(_packedData.length, _numberOfTriplets, 6); + revert CirclesErrorNoArgs(0xA6); } unpackedCoordinates_ = new uint16[](_numberOfTriplets * 3); @@ -1182,9 +1186,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * It will update the expiry time for the trusted address. */ function _upsertTrustMarker(address _truster, address _trusted, uint96 _expiry) private { - if (_truster == address(0)) revert CirclesLogicAssertion(1); - if (_trusted == address(0)) revert CirclesLogicAssertion(2); - if (_trusted == SENTINEL) revert CirclesLogicAssertion(3); + if (_truster == address(0) || _trusted == address(0) || _trusted == SENTINEL) { + revert CirclesErrorNoArgs(0x81); // CirclesLogicAssertion(1); + } TrustMarker storage sentinelMarker = trustMarkers[_truster][SENTINEL]; if (sentinelMarker.previous == address(0)) { diff --git a/src/lift/DemurrageCircles.sol b/src/lift/DemurrageCircles.sol index 81ff621..5b674b3 100644 --- a/src/lift/DemurrageCircles.sol +++ b/src/lift/DemurrageCircles.sol @@ -27,7 +27,8 @@ contract DemurrageCircles is MasterCopyNonUpgradable, ERC20DiscountedBalances, E modifier onlyHub(uint8 _code) { if (msg.sender != address(hub)) { - revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + // revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + revert CirclesErrorOneAddressArg(msg.sender, _code); } _; } @@ -46,14 +47,17 @@ contract DemurrageCircles is MasterCopyNonUpgradable, ERC20DiscountedBalances, E revert CirclesProxyAlreadyInitialized(); } if (address(_hub) == address(0)) { - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x04); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x05); } if (_avatar == address(0)) { - revert CirclesAddressCannotBeZero(2); + // revert CirclesAddressCannotBeZero(2); + revert CirclesErrorNoArgs(0x06); } hub = IHubV2(_hub); avatar = _avatar; @@ -97,7 +101,7 @@ contract DemurrageCircles is MasterCopyNonUpgradable, ERC20DiscountedBalances, E function onERC1155Received(address, address _from, uint256 _id, uint256 _amount, bytes memory) public override - onlyHub(0) + onlyHub(0xE1) returns (bytes4) { if (_id != toTokenId(avatar)) revert CirclesInvalidCirclesId(_id, 0); @@ -114,7 +118,7 @@ contract DemurrageCircles is MasterCopyNonUpgradable, ERC20DiscountedBalances, E public view override - onlyHub(1) + onlyHub(0xE2) returns (bytes4) { revert CirclesERC1155CannotReceiveBatch(0); diff --git a/src/lift/ERC20DiscountedBalances.sol b/src/lift/ERC20DiscountedBalances.sol index 9efbb13..8bdc1ef 100644 --- a/src/lift/ERC20DiscountedBalances.sol +++ b/src/lift/ERC20DiscountedBalances.sol @@ -79,9 +79,10 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { DiscountedBalance memory discountedBalance = discountedBalances[_account]; if (_day < discountedBalance.lastUpdatedDay) { // ERC20 DiscountedBalances: day is before last updated day - revert CirclesDemurrageDayBeforeLastUpdatedDay( - _account, toTokenId(avatar), _day, discountedBalance.lastUpdatedDay, 0 - ); + // revert CirclesDemurrageDayBeforeLastUpdatedDay( + // _account, toTokenId(avatar), _day, discountedBalance.lastUpdatedDay, 0 + // ); + revert CirclesErrorAddressUintArgs(_account, discountedBalance.lastUpdatedDay, 0xA2); } uint256 dayDifference; unchecked { @@ -105,7 +106,8 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { function _updateBalance(address _account, uint256 _balance, uint64 _day) internal { if (_balance > MAX_VALUE) { // Balance exceeds maximum value. - revert CirclesDemurrageAmountExceedsMaxUint190(_account, toTokenId(avatar), _balance, 0); + // revert CirclesDemurrageAmountExceedsMaxUint192(_account, toTokenId(avatar), _balance, 0); + revert CirclesErrorAddressUintArgs(_account, toTokenId(avatar), 0x83); } DiscountedBalance memory discountedBalance = discountedBalances[_account]; discountedBalance.balance = uint192(_balance); @@ -117,9 +119,10 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { DiscountedBalance memory discountedBalance = discountedBalances[_account]; if (_day < discountedBalance.lastUpdatedDay) { // ERC20 DiscountedBalances: day is before last updated day - revert CirclesDemurrageDayBeforeLastUpdatedDay( - _account, toTokenId(avatar), _day, discountedBalance.lastUpdatedDay, 1 - ); + // revert CirclesDemurrageDayBeforeLastUpdatedDay( + // _account, toTokenId(avatar), _day, discountedBalance.lastUpdatedDay, 1 + // ); + revert CirclesErrorAddressUintArgs(_account, discountedBalance.lastUpdatedDay, 0xA3); } uint256 dayDifference; unchecked { @@ -135,7 +138,8 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { uint256 updatedBalance = discountedBalanceOnDay + _value; if (updatedBalance > MAX_VALUE) { // Balance exceeds maximum value. - revert CirclesDemurrageAmountExceedsMaxUint190(_account, toTokenId(avatar), updatedBalance, 1); + // revert CirclesDemurrageAmountExceedsMaxUint192(_account, toTokenId(avatar), updatedBalance, 1); + revert CirclesErrorAddressUintArgs(_account, toTokenId(avatar), 0x84); } discountedBalance.balance = uint192(updatedBalance); discountedBalance.lastUpdatedDay = _day; diff --git a/src/lift/ERC20Lift.sol b/src/lift/ERC20Lift.sol index 1196f15..d3ccd25 100644 --- a/src/lift/ERC20Lift.sol +++ b/src/lift/ERC20Lift.sol @@ -8,7 +8,7 @@ import "../hub/IHub.sol"; import "../names/INameRegistry.sol"; import "../proxy/ProxyFactory.sol"; -contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors { +contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors, ICirclesCompactErrors { // Constants bytes4 public constant ERC20_WRAPPER_SETUP_CALLPREFIX = bytes4(keccak256("setup(address,address,address)")); @@ -40,19 +40,23 @@ contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors { ) { if (address(_hub) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x07); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x08); } if (_masterCopyERC20Demurrage == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(3); + // revert CirclesAddressCannotBeZero(3); + revert CirclesErrorNoArgs(0x09); } if (_masterCopyERC20Inflation == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(4); + // revert CirclesAddressCannotBeZero(4); + revert CirclesErrorNoArgs(0x0A); } hub = _hub; @@ -63,13 +67,9 @@ contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors { masterCopyERC20Wrapper[uint256(CirclesType.Inflation)] = _masterCopyERC20Inflation; } - // External functions - // Public functions function ensureERC20(address _avatar, CirclesType _circlesType) public returns (address) { - // todo: first build a simple proxy factory, afterwards redo for create2 deployment - // bytes32 salt = keccak256(abi.encodePacked(_id)); if (_circlesType != CirclesType.Demurrage && _circlesType != CirclesType.Inflation) { // Must be a valid CirclesType. revert CirclesInvalidParameter(uint256(_circlesType), 0); @@ -77,9 +77,12 @@ contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors { if (msg.sender != address(hub)) { // if the Hub calls it already has checked valid avatar - if (hub.avatars(_avatar) == address(0)) { - // Avatar must be registered. - revert CirclesAvatarMustBeRegistered(_avatar, 0); + // so when called independent from the Hub, check if the avatar + // is a registered human or group + if (!(hub.isHuman(_avatar) || hub.isGroup(_avatar))) { + // Avatar must be registered (as human or group) + // revert CirclesAvatarMustBeRegistered(_avatar, 0); + revert CirclesErrorOneAddressArg(_avatar, 0x26); } } diff --git a/src/lift/InflationaryCircles.sol b/src/lift/InflationaryCircles.sol index 720a8b7..b488e71 100644 --- a/src/lift/InflationaryCircles.sol +++ b/src/lift/InflationaryCircles.sol @@ -31,7 +31,8 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc modifier onlyHub(uint8 _code) { if (msg.sender != address(hub)) { - revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + // revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + revert CirclesErrorOneAddressArg(msg.sender, _code); } _; } @@ -52,15 +53,18 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc } if (address(_hub) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x0B); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x0C); } if (_avatar == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(2); + // revert CirclesAddressCannotBeZero(2); + revert CirclesErrorNoArgs(0x0D); } hub = IHubV2(_hub); avatar = _avatar; @@ -86,7 +90,7 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc } function name() external view returns (string memory) { - // append suffix for "ERC20 static" to the ERC20 name + // append suffix for "-ERC20s" to the ERC20 name (s for "static") return string(abi.encodePacked(nameRegistry.name(avatar), "-ERC20s")); } @@ -103,7 +107,7 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc function onERC1155Received(address, address _from, uint256 _id, uint256 _amount, bytes memory) public override - onlyHub(0) + onlyHub(0xE3) returns (bytes4) { if (_id != toTokenId(avatar)) revert CirclesInvalidCirclesId(_id, 0); @@ -119,7 +123,7 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc public view override - onlyHub(1) + onlyHub(0xE4) returns (bytes4) { revert CirclesERC1155CannotReceiveBatch(0); diff --git a/src/migration/Migration.sol b/src/migration/Migration.sol index 2830d9a..94776ff 100644 --- a/src/migration/Migration.sol +++ b/src/migration/Migration.sol @@ -6,7 +6,7 @@ import "../hub/IHub.sol"; import "./IHub.sol"; import "./IToken.sol"; -contract Migration is ICirclesErrors { +contract Migration is ICirclesErrors, IMigrationErrors, ICirclesCompactErrors { // Constant uint256 private constant ACCURACY = uint256(10 ** 8); @@ -32,11 +32,13 @@ contract Migration is ICirclesErrors { constructor(IHubV1 _hubV1, IHubV2 _hubV2, uint256 _inflationDayZero) { if (address(_hubV1) == address(0)) { // Hub v1 address can not be zero. - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x0E); } if (address(_hubV2) == address(0)) { // Hub v2 address can not be zero. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x0F); } hubV1 = _hubV1; @@ -64,7 +66,8 @@ contract Migration is ICirclesErrors { function migrate(address[] calldata _avatars, uint256[] calldata _amounts) external returns (uint256[] memory) { if (_avatars.length != _amounts.length) { // Arrays length mismatch. - revert CirclesArraysLengthMismatch(_avatars.length, _amounts.length, 0); + // revert CirclesArraysLengthMismatch(_avatars.length, _amounts.length, 0); + revert CirclesErrorNoArgs(0xA7); } uint256[] memory convertedAmounts = new uint256[](_avatars.length); @@ -73,7 +76,12 @@ contract Migration is ICirclesErrors { ITokenV1 circlesV1 = ITokenV1(hubV1.userToToken(_avatars[i])); if (address(circlesV1) == address(0)) { // Invalid avatar, not registered in hub V1. - revert CirclesAddressCannotBeZero(2); + // revert CirclesAddressCannotBeZero(2); + revert CirclesErrorNoArgs(0x10); + } + if (_amounts[i] == 0) { + // Amount must be greater than zero. + revert CirclesMigrationAmountMustBeGreaterThanZero(); } convertedAmounts[i] = convertFromV1ToDemurrage(_amounts[i]); // transfer the v1 Circles to this contract to be locked diff --git a/src/names/NameRegistry.sol b/src/names/NameRegistry.sol index fff400a..2e0f5f9 100644 --- a/src/names/NameRegistry.sol +++ b/src/names/NameRegistry.sol @@ -6,7 +6,7 @@ import "../hub/IHub.sol"; import "./Base58Converter.sol"; import "./INameRegistry.sol"; -contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, ICirclesErrors { +contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, ICirclesErrors, ICirclesCompactErrors { // Constants /** @@ -63,16 +63,10 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC // Modifiers - modifier mustBeRegistered(address _avatar, uint8 _code) { - if (hub.avatars(_avatar) == address(0)) { - revert CirclesAvatarMustBeRegistered(_avatar, _code); - } - _; - } - modifier onlyHub(uint8 _code) { if (msg.sender != address(hub)) { - revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + // revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + revert CirclesErrorOneAddressArg(msg.sender, _code); } _; } @@ -82,7 +76,8 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC constructor(IHubV2 _hub) { if (address(_hub) == address(0)) { // Hub cannot be the zero address. - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x11); } hub = _hub; } @@ -92,7 +87,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC /** * @notice Register a short name for the avatar */ - function registerShortName() external mustBeRegistered(msg.sender, 0) { + function registerShortName() external { _registerShortName(); } @@ -100,19 +95,19 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC * Registers a short name for the avatar using a specific nonce if the short name is available * @param _nonce nonce to be used in the calculation */ - function registerShortNameWithNonce(uint256 _nonce) external mustBeRegistered(msg.sender, 1) { + function registerShortNameWithNonce(uint256 _nonce) external { _registerShortNameWithNonce(_nonce); } - function setMetadataDigest(address _avatar, bytes32 _metadataDigest) external onlyHub(0) { + function setMetadataDigest(address _avatar, bytes32 _metadataDigest) external onlyHub(0xE5) { _setMetadataDigest(_avatar, _metadataDigest); } - function updateMetadataDigest(bytes32 _metadataDigest) external mustBeRegistered(msg.sender, 2) { + function updateMetadataDigest(bytes32 _metadataDigest) external { _setMetadataDigest(msg.sender, _metadataDigest); } - function registerCustomName(address _avatar, string calldata _name) external onlyHub(1) { + function registerCustomName(address _avatar, string calldata _name) external onlyHub(0xE6) { if (bytes(_name).length == 0) { // if name is left empty, it will default to default name "Circles-" return; @@ -123,7 +118,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC customNames[_avatar] = _name; } - function registerCustomSymbol(address _avatar, string calldata _symbol) external onlyHub(2) { + function registerCustomSymbol(address _avatar, string calldata _symbol) external onlyHub(0xE7) { if (bytes(_symbol).length == 0) { // if symbol is left empty, it will default to default symbol "CRC" return; @@ -134,7 +129,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC customSymbols[_avatar] = _symbol; } - function name(address _avatar) external view mustBeRegistered(_avatar, 3) returns (string memory) { + function name(address _avatar) external view returns (string memory) { if (!hub.isHuman(_avatar)) { // groups and organizations can have set a custom name string memory customName = customNames[_avatar]; @@ -148,7 +143,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC return _getShortOrLongName(_avatar); } - function symbol(address _avatar) external view mustBeRegistered(_avatar, 4) returns (string memory) { + function symbol(address _avatar) external view returns (string memory) { if (hub.isOrganization(_avatar)) { revert CirclesNamesOrganizationHasNoSymbol(_avatar, 0); } @@ -292,6 +287,11 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC } function _storeShortName(address _avatar, uint72 _shortName, uint256 _nonce) internal { + if (_shortName == uint72(0)) { + // short name cannot be zero (but congrats if you got it!) + // this would break the reverse lookup + revert CirclesNamesShortNameZero(_avatar, _nonce); + } // assign the name to the address shortNames[_avatar] = _shortName; // assign the address to the name diff --git a/src/operators/BaseOperator.sol b/src/operators/BaseOperator.sol index 5060689..0a73038 100644 --- a/src/operators/BaseOperator.sol +++ b/src/operators/BaseOperator.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.24; import "../errors/Errors.sol"; import "../hub/IHub.sol"; -contract BaseOperator is ICirclesErrors { +contract BaseOperator is ICirclesErrors, ICirclesCompactErrors { // State variables IHubV2 public hub; @@ -14,7 +14,8 @@ contract BaseOperator is ICirclesErrors { constructor(IHubV2 _hub) { if (address(_hub) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x12); } hub = _hub; diff --git a/src/operators/SignedPathOperator.sol b/src/operators/SignedPathOperator.sol index f7948e8..936b1e3 100644 --- a/src/operators/SignedPathOperator.sol +++ b/src/operators/SignedPathOperator.sol @@ -29,7 +29,8 @@ contract SignedPathOperator is BaseOperator, TypeDefinitions { address source = _flowVertices[_sourceCoordinate]; // Ensure the source is the caller if (msg.sender != source) { - revert CirclesInvalidFunctionCaller(msg.sender, source, 0); + // revert CirclesInvalidFunctionCaller(msg.sender, source, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0xEA); } // check that for every stream the source of the stream matches the alleged single source diff --git a/src/treasury/StandardTreasury.sol b/src/treasury/StandardTreasury.sol index 3437ba5..081bbe5 100644 --- a/src/treasury/StandardTreasury.sol +++ b/src/treasury/StandardTreasury.sol @@ -17,7 +17,8 @@ contract StandardTreasury is TypeDefinitions, IERC1155Receiver, ICirclesErrors, - IStandardTreasuryErrors + IStandardTreasuryErrors, + ICirclesCompactErrors { // Constants @@ -50,8 +51,8 @@ contract StandardTreasury is // Events event CreateVault(address indexed group, address indexed vault); - event GroupMintSingle(address indexed group, uint256 indexed id, uint256 value, bytes userData); - event GroupMintBatch(address indexed group, uint256[] ids, uint256[] values, bytes userData); + event CollateralLockedSingle(address indexed group, uint256 indexed id, uint256 value, bytes userData); + event CollateralLockedBatch(address indexed group, uint256[] ids, uint256[] values, bytes userData); event GroupRedeem(address indexed group, uint256 indexed id, uint256 value, bytes data); event GroupRedeemCollateralReturn(address indexed group, address indexed to, uint256[] ids, uint256[] values); event GroupRedeemCollateralBurn(address indexed group, uint256[] ids, uint256[] values); @@ -61,10 +62,11 @@ contract StandardTreasury is /** * @notice Ensure the caller is the hub */ - modifier onlyHub() { + modifier onlyHub(uint8 _code) { if (msg.sender != address(hub)) { // Treasury: caller is not the hub - revert CirclesInvalidFunctionCaller(msg.sender, address(hub), 0); + // revert CirclesInvalidFunctionCaller(msg.sender, address(hub), 0); + revert CirclesErrorOneAddressArg(msg.sender, _code); } _; } @@ -79,11 +81,13 @@ contract StandardTreasury is constructor(IHubV2 _hub, address _mastercopyStandardVault) { if (address(_hub) == address(0)) { // Hub address cannot be 0 - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x13); } if (_mastercopyStandardVault == address(0)) { // Mastercopy standard vault address cannot be 0 - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x14); } hub = _hub; mastercopyStandardVault = _mastercopyStandardVault; @@ -105,14 +109,14 @@ contract StandardTreasury is function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) public override - onlyHub + onlyHub(0xE8) returns (bytes4) { (bytes32 metadataType, address group, bytes memory userData) = _decodeMetadataForGroup(_data); if (metadataType == METADATATYPE_GROUPMINT) { - return _mintGroupCircles(_id, _value, group, userData); + return _lockCollateralGroupCircles(_id, _value, group, userData); } else if (metadataType == METADATATYPE_GROUPREDEEM) { - return _redeemGroupCircles(_operator, _from, _id, _value, _data); + return _redeemGroupCircles(_operator, _from, _id, _value, userData); } else { // Treasury: Invalid metadata type for received revert CirclesStandardTreasuryInvalidMetadataType(metadataType, 0); @@ -129,10 +133,10 @@ contract StandardTreasury is uint256[] memory _ids, uint256[] memory _values, bytes calldata _data - ) public override onlyHub returns (bytes4) { + ) public override onlyHub(0xE9) returns (bytes4) { (bytes32 metadataType, address group, bytes memory userData) = _decodeMetadataForGroup(_data); if (metadataType == METADATATYPE_GROUPMINT) { - return _mintBatchGroupCircles(_ids, _values, group, userData); + return _lockCollateralBatchGroupCircles(_ids, _values, group, userData); } else { // Treasury: Invalid metadata type for batch received revert CirclesStandardTreasuryInvalidMetadataType(metadataType, 1); @@ -144,7 +148,7 @@ contract StandardTreasury is // onReceived : either mint if data decodes or redeem // onBatchReceived : only for minting if data matches - function _mintBatchGroupCircles( + function _lockCollateralBatchGroupCircles( uint256[] memory _ids, uint256[] memory _values, address _group, @@ -155,13 +159,13 @@ contract StandardTreasury is // forward the Circles to the vault hub.safeBatchTransferFrom(address(this), vault, _ids, _values, _userData); - // emit the group mint event - emit GroupMintBatch(_group, _ids, _values, _userData); + // emit the collateral locked event + emit CollateralLockedBatch(_group, _ids, _values, _userData); return this.onERC1155BatchReceived.selector; } - function _mintGroupCircles(uint256 _id, uint256 _value, address _group, bytes memory _userData) + function _lockCollateralGroupCircles(uint256 _id, uint256 _value, address _group, bytes memory _userData) internal returns (bytes4) { @@ -170,13 +174,13 @@ contract StandardTreasury is // forward the Circles to the vault hub.safeTransferFrom(address(this), vault, _id, _value, _userData); - // emit the group mint event - emit GroupMintSingle(_group, _id, _value, _userData); + // emit the collateral locked event + emit CollateralLockedSingle(_group, _id, _value, _userData); return this.onERC1155Received.selector; } - function _redeemGroupCircles(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) + function _redeemGroupCircles(address _operator, address _from, uint256 _id, uint256 _value, bytes memory _userData) internal returns (bytes4) { @@ -191,7 +195,8 @@ contract StandardTreasury is IMintPolicy policy = IMintPolicy(hub.mintPolicies(group)); if (address(policy) == address(0)) { // Treasury: Invalid group without mint policy - revert CirclesLogicAssertion(0); + // revert CirclesLogicAssertion(0); + revert CirclesErrorNoArgs(0x85); } // query the mint policy for the redemption values @@ -200,7 +205,7 @@ contract StandardTreasury is uint256[] memory burnIds; uint256[] memory burnValues; (redemptionIds, redemptionValues, burnIds, burnValues) = - policy.beforeRedeemPolicy(_operator, _from, group, _value, _data); + policy.beforeRedeemPolicy(_operator, _from, group, _value, _userData); // ensure the redemption values sum up to the correct amount uint256 sum = 0; @@ -218,16 +223,16 @@ contract StandardTreasury is } // burn the group Circles - hub.burn(_id, _value, _data); + hub.burn(_id, _value, _userData); // return collateral Circles to the redeemer of group Circles - vault.returnCollateral(_from, redemptionIds, redemptionValues, _data); + vault.returnCollateral(_from, redemptionIds, redemptionValues, _userData); // burn the collateral Circles from the vault - vault.burnCollateral(burnIds, burnValues, _data); + vault.burnCollateral(burnIds, burnValues, _userData); // emit the group redeem event - emit GroupRedeem(group, _id, _value, _data); + emit GroupRedeem(group, _id, _value, _userData); emit GroupRedeemCollateralReturn(group, _from, redemptionIds, redemptionValues); emit GroupRedeemCollateralBurn(group, burnIds, burnValues); diff --git a/src/treasury/StandardVault.sol b/src/treasury/StandardVault.sol index 15b695b..049473c 100644 --- a/src/treasury/StandardVault.sol +++ b/src/treasury/StandardVault.sol @@ -7,7 +7,13 @@ import "../hub/IHub.sol"; import "../proxy/MasterCopyNonUpgradable.sol"; import "./IStandardVault.sol"; -contract StandardVault is MasterCopyNonUpgradable, ERC1155Holder, IStandardVault, ICirclesErrors { +contract StandardVault is + MasterCopyNonUpgradable, + ERC1155Holder, + IStandardVault, + ICirclesErrors, + ICirclesCompactErrors +{ // State variables /** @@ -28,7 +34,8 @@ contract StandardVault is MasterCopyNonUpgradable, ERC1155Holder, IStandardVault modifier onlyTreasury() { if (msg.sender != standardTreasury) { // Vault: caller is not the treasury - revert CirclesInvalidFunctionCaller(msg.sender, standardTreasury, 0); + // revert CirclesInvalidFunctionCaller(msg.sender, standardTreasury, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0xEB); } _; } @@ -74,7 +81,8 @@ contract StandardVault is MasterCopyNonUpgradable, ERC1155Holder, IStandardVault ) external onlyTreasury { if (_receiver == address(0)) { // Vault: receiver cannot be 0 address - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x15); } // return the collateral to the receiver @@ -93,7 +101,8 @@ contract StandardVault is MasterCopyNonUpgradable, ERC1155Holder, IStandardVault { if (_ids.length != _values.length) { // Vault: ids and values length mismatch - revert CirclesArraysLengthMismatch(_ids.length, _values.length, 0); + // revert CirclesArraysLengthMismatch(_ids.length, _values.length, 0); + revert CirclesErrorNoArgs(0xA8); } // burn the collateral from the vault