From 9f3a0df63105841a9ea0105cc21e06a52c6695d4 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 25 Sep 2024 21:51:54 +0100 Subject: [PATCH 01/45] (hub): non-Reentrant modifier had unused error code; remove --- src/hub/Hub.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index b99a4a9..431a3ef 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -143,7 +143,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) @@ -543,7 +543,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); From 1db4d65da2d431d965eeeb199040b87d0351f5d5 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 25 Sep 2024 22:03:04 +0100 Subject: [PATCH 02/45] (circles): correct order of check and effect in _claimIssuance to prevent reentrancy attack (patch 01) --- src/circles/Circles.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 45d2c63..dfb84ed 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -138,11 +138,12 @@ 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, ""); + emit PersonalMint(_human, issuance, startPeriod, endPeriod); } From 3a209d730e1ca927057b4735e5f94ef8394ed7c9 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 26 Sep 2024 17:00:23 +0200 Subject: [PATCH 03/45] (hub): on update v1 status, never reduce lastMintTime to avoid resetting stopped status --- src/circles/Circles.sol | 4 +--- src/hub/Hub.sol | 4 +++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 45d2c63..4174b2a 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -185,14 +185,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/hub/Hub.sol b/src/hub/Hub.sol index b99a4a9..c669faa 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -1117,7 +1117,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // 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))); } } From fcde6871f778a92da64e65005b62dacae53ee5f1 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 26 Sep 2024 17:26:18 +0200 Subject: [PATCH 04/45] (Hub, InflatCRC, Circles): tidy up unused variable, docstring, comment --- src/circles/Circles.sol | 6 ------ src/hub/Hub.sol | 4 ++-- src/lift/InflationaryCircles.sol | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 45d2c63..9255688 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. diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index b99a4a9..8777531 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; diff --git a/src/lift/InflationaryCircles.sol b/src/lift/InflationaryCircles.sol index 720a8b7..4787747 100644 --- a/src/lift/InflationaryCircles.sol +++ b/src/lift/InflationaryCircles.sol @@ -86,7 +86,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")); } From 7efb87ff9c30cb3240ada5ee300817f2a541a9f1 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 26 Sep 2024 17:39:13 +0200 Subject: [PATCH 05/45] (erc20Lift): only deploy erc20 wrapper for humans or groups (not for organizations) --- src/lift/ERC20Lift.sol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lift/ERC20Lift.sol b/src/lift/ERC20Lift.sol index 1196f15..48b5ead 100644 --- a/src/lift/ERC20Lift.sol +++ b/src/lift/ERC20Lift.sol @@ -77,8 +77,10 @@ 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. + // 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); } } From c2a520f5f75d045be1b45bc334ecbea0d6f647f2 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 26 Sep 2024 17:46:09 +0200 Subject: [PATCH 06/45] (erc20Lift): quick extra cleanup of comments --- src/lift/ERC20Lift.sol | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/lift/ERC20Lift.sol b/src/lift/ERC20Lift.sol index 48b5ead..0dab9e9 100644 --- a/src/lift/ERC20Lift.sol +++ b/src/lift/ERC20Lift.sol @@ -63,13 +63,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); @@ -80,7 +76,7 @@ contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors { // 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). + // Avatar must be registered (as human or group) revert CirclesAvatarMustBeRegistered(_avatar, 0); } } From e25ede414039f603480173bbcd1953ec2476973c Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 30 Sep 2024 18:36:55 +0200 Subject: [PATCH 07/45] (Circles): correct issuance function for calculating exactly on a completed hour --- src/circles/Circles.sol | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 45d2c63..396bbfb 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -113,9 +113,20 @@ contract Circles is ERC1155, ICirclesErrors { 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); + int128 l; + uint256 secondsRemainingInB = ((dB + 1) * 1 days + inflationDayZero - block.timestamp); + if ((secondsRemainingInB % 1 hours) == 0) { + // to count the incompleted hours remaining in day B, when claiming issuance on exactly a full hour, + // we can simply take the integer division, as the preceding hour has just completed. + l = Math64x64.fromUInt(secondsRemainingInB / 1 hours); + } else { + // however, most often the issuance is not on the rounded hour exactly, so the current hour has not yet + // completed and we should not yet issue it (and substract an extra hour for the current hour) + l = Math64x64.fromUInt((secondsRemainingInB / 1 hours) + 1); + } // 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 From a6cd3ea8809a7fe61d33ca7b6a710e1e202b7916 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 30 Sep 2024 18:45:11 +0200 Subject: [PATCH 08/45] (hub): correct trivial error in error in _matchNettedFlows --- src/hub/Hub.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index b99a4a9..6483a71 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -959,7 +959,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { 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]); } } } From 61be206952417d0c6fa5796eec785f0c7db5575b Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 30 Sep 2024 19:08:08 +0200 Subject: [PATCH 09/45] (hub, circles): suppress group mint's acceptance call if along a path and not terminal flow --- src/circles/Circles.sol | 12 +++++++++--- src/circles/ERC1155.sol | 9 +++++++-- src/hub/Hub.sol | 8 +++++--- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 45d2c63..b765c56 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -139,15 +139,21 @@ contract Circles is ERC1155, ICirclesErrors { return; } // mint personal Circles to the human - _mintAndUpdateTotalSupply(_human, toTokenId(_human), issuance, ""); + _mintAndUpdateTotalSupply(_human, toTokenId(_human), issuance, "", true); // update the last mint time mintTimes[_human].lastMintTime = uint96(block.timestamp); 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]; 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/hub/Hub.sol b/src/hub/Hub.sol index b99a4a9..be8bfd0 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -260,7 +260,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); } } @@ -499,7 +499,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { 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); } } @@ -726,7 +726,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { 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); + // 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); } /** From 5a55b0c75613732de30fcf28a56eae2d1b026dc0 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 30 Sep 2024 21:25:57 +0100 Subject: [PATCH 10/45] (demurrage): small possible gas optimisation --- src/circles/Demurrage.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/circles/Demurrage.sol b/src/circles/Demurrage.sol index 92ed82f..2f26c5e 100644 --- a/src/circles/Demurrage.sol +++ b/src/circles/Demurrage.sol @@ -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); } /** From 8c857ce712e1f81bafebb855440d808b02a28ac7 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 1 Oct 2024 15:54:19 +0100 Subject: [PATCH 11/45] (migration): require migration amount to be greater than zero --- src/errors/Errors.sol | 4 ++++ src/migration/Migration.sol | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 155d4d0..6d6e768 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -96,3 +96,7 @@ interface INameRegistryErrors { error CirclesNamesOrganizationHasNoSymbol(address organization, uint8 code); } + +interface IMigrationErrors { + error CirclesMigrationAmountMustBeGreaterThanZero(); +} diff --git a/src/migration/Migration.sol b/src/migration/Migration.sol index 2830d9a..b7d6e13 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 { // Constant uint256 private constant ACCURACY = uint256(10 ** 8); @@ -75,6 +75,10 @@ contract Migration is ICirclesErrors { // Invalid avatar, not registered in hub V1. revert CirclesAddressCannotBeZero(2); } + 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 circlesV1.transferFrom(msg.sender, address(this), _amounts[i]); From f8a5e08d09aa65471c939496c72856a524493d05 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 1 Oct 2024 21:31:55 +0100 Subject: [PATCH 12/45] (circles): improve the impl so save compile size and improve readability --- src/circles/Circles.sol | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 396bbfb..971f6bf 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -112,18 +112,14 @@ 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; + // Calculate the number of seconds remaining in the current day (dB) uint256 secondsRemainingInB = ((dB + 1) * 1 days + inflationDayZero - block.timestamp); - if ((secondsRemainingInB % 1 hours) == 0) { - // to count the incompleted hours remaining in day B, when claiming issuance on exactly a full hour, - // we can simply take the integer division, as the preceding hour has just completed. - l = Math64x64.fromUInt(secondsRemainingInB / 1 hours); - } else { - // however, most often the issuance is not on the rounded hour exactly, so the current hour has not yet - // completed and we should not yet issue it (and substract an extra hour for the current hour) - l = Math64x64.fromUInt((secondsRemainingInB / 1 hours) + 1); - } + // 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 From 10bb27ae7605aa78766e96c656e6a533722380be Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 1 Oct 2024 21:43:10 +0100 Subject: [PATCH 13/45] (InflationaryOperator): initialise inflationDayZero from Hub --- src/circles/InflationaryOperator.sol | 2 ++ 1 file changed, 2 insertions(+) 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 From 78cc375558cba50a1ab56a8d5c9660832e6e70e5 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 1 Oct 2024 22:12:14 +0100 Subject: [PATCH 14/45] (StandardTreasury): improve accuracy of name of events and func --- src/treasury/StandardTreasury.sol | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/treasury/StandardTreasury.sol b/src/treasury/StandardTreasury.sol index 3437ba5..9440efd 100644 --- a/src/treasury/StandardTreasury.sol +++ b/src/treasury/StandardTreasury.sol @@ -50,8 +50,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); @@ -110,7 +110,7 @@ contract StandardTreasury is { (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); } else { @@ -132,7 +132,7 @@ contract StandardTreasury is ) public override onlyHub 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 +144,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 +155,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,8 +170,8 @@ 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; } From cf4ba339745acc843582c70b5290888f4ee70c89 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 1 Oct 2024 22:18:15 +0100 Subject: [PATCH 15/45] (hub): adding explicit GroupMint event to Hub, TBD if we can find space for it --- src/hub/Hub.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index b99a4a9..6515a22 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -127,6 +127,15 @@ 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, + bytes data + ); + // Modifiers /** @@ -727,6 +736,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // mint group Circles to the receiver and send the original _data onwards _mintAndUpdateTotalSupply(_receiver, toTokenId(_group), sumAmounts, _data); + + // emit the group mint event + emit GroupMint(_sender, _receiver, _group, _collateral, _amounts, _data); } /** From 7ca31f9e2b5dc66d452178f2cc698edc6551fd14 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 1 Oct 2024 22:28:04 +0100 Subject: [PATCH 16/45] (hub): simplify GroupMint event to reduce code size --- src/hub/Hub.sol | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 6515a22..0802877 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -128,12 +128,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { ); event GroupMint( - address indexed sender, - address indexed receiver, - address indexed group, - uint256[] collateral, - uint256[] amounts, - bytes data + address indexed sender, address indexed receiver, address indexed group, uint256[] collateral, uint256[] amounts ); // Modifiers @@ -738,7 +733,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { _mintAndUpdateTotalSupply(_receiver, toTokenId(_group), sumAmounts, _data); // emit the group mint event - emit GroupMint(_sender, _receiver, _group, _collateral, _amounts, _data); + emit GroupMint(_sender, _receiver, _group, _collateral, _amounts); } /** From d7406b5229911c3e65b490d441b66c7da7380ad9 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 1 Oct 2024 22:44:33 +0100 Subject: [PATCH 17/45] (errors): rename variable in error for correctness --- src/errors/Errors.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 155d4d0..b1fc6a5 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -18,7 +18,7 @@ interface IHubErrors { error CirclesHubGroupMintPolicyRejectedBurn(address burner, address group, uint256 amount, bytes data, uint8 code); - error CirclesHubOperatorNotApprovedForSource(address operator, address source, uint16 streamId, uint8 code); + error CirclesHubOperatorNotApprovedForSource(address operator, address source, uint16 streamIndex, uint8 code); error CirclesHubFlowEdgeIsNotPermitted(address receiver, uint256 circlesId, uint8 code); From 39540354b1463c9476032840a1ae2014d2c37bc4 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 1 Oct 2024 22:58:49 +0100 Subject: [PATCH 18/45] (nameRegistry): check short name is not zero --- src/errors/Errors.sol | 2 ++ src/names/NameRegistry.sol | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 155d4d0..c4ac305 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -95,4 +95,6 @@ interface INameRegistryErrors { error CirclesNamesAvatarAlreadyHasCustomNameOrSymbol(address avatar, string nameOrSymbol, uint8 code); error CirclesNamesOrganizationHasNoSymbol(address organization, uint8 code); + + error CirclesNamesShortNameZero(address avatar, uint256 nonce); } diff --git a/src/names/NameRegistry.sol b/src/names/NameRegistry.sol index fff400a..890f313 100644 --- a/src/names/NameRegistry.sol +++ b/src/names/NameRegistry.sol @@ -292,6 +292,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 From ae3e110b7671ff42cd1a084c22d92bcd047073ab Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 1 Oct 2024 23:05:42 +0100 Subject: [PATCH 19/45] (nameRegistry): remove restriction only registered address can register short name --- src/names/NameRegistry.sol | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/names/NameRegistry.sol b/src/names/NameRegistry.sol index fff400a..1f983e2 100644 --- a/src/names/NameRegistry.sol +++ b/src/names/NameRegistry.sol @@ -63,13 +63,6 @@ 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); @@ -92,7 +85,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,7 +93,7 @@ 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); } @@ -108,7 +101,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC _setMetadataDigest(_avatar, _metadataDigest); } - function updateMetadataDigest(bytes32 _metadataDigest) external mustBeRegistered(msg.sender, 2) { + function updateMetadataDigest(bytes32 _metadataDigest) external { _setMetadataDigest(msg.sender, _metadataDigest); } @@ -134,7 +127,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 +141,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); } From ce7d2adcda6e64331ad1f7e8bbd4427684d6579b Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 2 Oct 2024 19:49:16 +0100 Subject: [PATCH 20/45] (circles): update check for calculate issuance to more accurately check an hour is available --- src/circles/Circles.sol | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 45d2c63..93d8661 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -91,12 +91,26 @@ contract Circles is ERC1155, ICirclesErrors { revert CirclesERC1155MintBlocked(_human, mintTime.mintV1Status); } - 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 + // Early check for stopped mints + if (mintTime.lastMintTime == INDEFINITE_FUTURE) { return (0, 0, 0); } + // 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) { + // No new completed hour to mint + return (0, 0, 0); + } + + // 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 + // return (0, 0, 0); + // } + // calculate the start of the claimable period uint256 startMint = _max(block.timestamp - MAX_CLAIM_DURATION, mintTime.lastMintTime); From 408b7ced22c0c39e73b81e4b66f418c370555d32 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 2 Oct 2024 19:57:18 +0100 Subject: [PATCH 21/45] (circles): remove commented out code --- src/circles/Circles.sol | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 93d8661..d31449b 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -105,12 +105,6 @@ contract Circles is ERC1155, ICirclesErrors { return (0, 0, 0); } - // 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 - // return (0, 0, 0); - // } - // calculate the start of the claimable period uint256 startMint = _max(block.timestamp - MAX_CLAIM_DURATION, mintTime.lastMintTime); From b00072c81a24b222e6620e52cf7cb18b2434faea Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 2 Oct 2024 21:05:48 +0100 Subject: [PATCH 22/45] (StandardTreasury): correct data passed to be user data to policy for redeem --- src/treasury/StandardTreasury.sol | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/treasury/StandardTreasury.sol b/src/treasury/StandardTreasury.sol index 3437ba5..c629119 100644 --- a/src/treasury/StandardTreasury.sol +++ b/src/treasury/StandardTreasury.sol @@ -112,7 +112,7 @@ contract StandardTreasury is if (metadataType == METADATATYPE_GROUPMINT) { return _mintGroupCircles(_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); @@ -176,7 +176,7 @@ contract StandardTreasury is 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) { @@ -200,7 +200,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 +218,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); From 4b44c29aa089f898e92eda7168a2832b07af7994 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 2 Oct 2024 22:37:30 +0100 Subject: [PATCH 23/45] (error): CirclesErrorNoArgs <- 0: CirclesAddressCannotBeZero --- src/circles/Demurrage.sol | 2 +- src/errors/Errors.sol | 12 +++++++++++- src/hub/Hub.sol | 12 ++++++++---- src/lift/DemurrageCircles.sol | 9 ++++++--- src/lift/ERC20Lift.sol | 14 +++++++++----- src/lift/InflationaryCircles.sol | 9 ++++++--- src/migration/Migration.sol | 11 +++++++---- src/names/NameRegistry.sol | 5 +++-- src/operators/BaseOperator.sol | 5 +++-- src/treasury/StandardTreasury.sol | 9 ++++++--- src/treasury/StandardVault.sol | 11 +++++++++-- 11 files changed, 69 insertions(+), 30 deletions(-) diff --git a/src/circles/Demurrage.sol b/src/circles/Demurrage.sol index 2f26c5e..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 /** diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 0c8d23c..bdbaa10 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -1,6 +1,15 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.24; +interface ICirclesCompactErrors { + /** + * @dev CirclesErrorNoArgs is a generic error that does not require any arguments. + * errorId: + * 0: CirclesAddressCannotBeZero + */ + error CirclesErrorNoArgs(uint8 errorId, uint8 occuranceCode); +} + interface IHubErrors { error CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(address avatar, uint8 code); @@ -46,7 +55,8 @@ interface ICirclesDemurrageErrors { interface ICirclesErrors { error CirclesAvatarMustBeRegistered(address avatar, uint8 code); - error CirclesAddressCannotBeZero(uint8 code); + // CirclesErrorNoArgs 0 + // error CirclesAddressCannotBeZero(uint8 code); error CirclesInvalidFunctionCaller(address caller, address expectedCaller, uint8 code); diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index f897420..e6a081c 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -182,10 +182,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(0, 0); } if (_standardTreasury == address(0)) { - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0, 1); } // initialize linked list for avatars @@ -1016,12 +1018,14 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // todo: we could check ERC165 support interface for mint policy if (_mint == address(0)) { // Mint address can not be zero. - revert CirclesAddressCannotBeZero(2); + // revert CirclesAddressCannotBeZero(2); + revert CirclesErrorNoArgs(0, 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 CirclesAddressCannotBeZero(3); + revert CirclesErrorNoArgs(0, 3); } if (!nameRegistry.isValidName(_name)) { // Invalid group name. diff --git a/src/lift/DemurrageCircles.sol b/src/lift/DemurrageCircles.sol index 81ff621..9803526 100644 --- a/src/lift/DemurrageCircles.sol +++ b/src/lift/DemurrageCircles.sol @@ -46,14 +46,17 @@ contract DemurrageCircles is MasterCopyNonUpgradable, ERC20DiscountedBalances, E revert CirclesProxyAlreadyInitialized(); } if (address(_hub) == address(0)) { - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0, 4); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0, 5); } if (_avatar == address(0)) { - revert CirclesAddressCannotBeZero(2); + // revert CirclesAddressCannotBeZero(2); + revert CirclesErrorNoArgs(0, 6); } hub = IHubV2(_hub); avatar = _avatar; diff --git a/src/lift/ERC20Lift.sol b/src/lift/ERC20Lift.sol index 0dab9e9..8f705e0 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(0, 7); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0, 8); } if (_masterCopyERC20Demurrage == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(3); + // revert CirclesAddressCannotBeZero(3); + revert CirclesErrorNoArgs(0, 9); } if (_masterCopyERC20Inflation == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(4); + // revert CirclesAddressCannotBeZero(4); + revert CirclesErrorNoArgs(0, 10); } hub = _hub; diff --git a/src/lift/InflationaryCircles.sol b/src/lift/InflationaryCircles.sol index 4787747..f8cc734 100644 --- a/src/lift/InflationaryCircles.sol +++ b/src/lift/InflationaryCircles.sol @@ -52,15 +52,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(0, 11); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0, 12); } if (_avatar == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(2); + // revert CirclesAddressCannotBeZero(2); + revert CirclesErrorNoArgs(0, 13); } hub = IHubV2(_hub); avatar = _avatar; diff --git a/src/migration/Migration.sol b/src/migration/Migration.sol index b7d6e13..f634424 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, IMigrationErrors { +contract Migration is ICirclesErrors, IMigrationErrors, ICirclesCompactErrors { // Constant uint256 private constant ACCURACY = uint256(10 ** 8); @@ -32,11 +32,13 @@ contract Migration is ICirclesErrors, IMigrationErrors { 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(0, 14); } if (address(_hubV2) == address(0)) { // Hub v2 address can not be zero. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0, 15); } hubV1 = _hubV1; @@ -73,7 +75,8 @@ contract Migration is ICirclesErrors, IMigrationErrors { 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(0, 16); } if (_amounts[i] == 0) { // Amount must be greater than zero. diff --git a/src/names/NameRegistry.sol b/src/names/NameRegistry.sol index 1a15d58..0da2178 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 /** @@ -75,7 +75,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(0, 17); } hub = _hub; } diff --git a/src/operators/BaseOperator.sol b/src/operators/BaseOperator.sol index 5060689..5dc6f60 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(0, 18); } hub = _hub; diff --git a/src/treasury/StandardTreasury.sol b/src/treasury/StandardTreasury.sol index 2a6534c..0bd5207 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 @@ -79,11 +80,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(0, 19); } if (_mastercopyStandardVault == address(0)) { // Mastercopy standard vault address cannot be 0 - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0, 20); } hub = _hub; mastercopyStandardVault = _mastercopyStandardVault; diff --git a/src/treasury/StandardVault.sol b/src/treasury/StandardVault.sol index 15b695b..475a596 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 /** @@ -74,7 +80,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(0, 21); } // return the collateral to the receiver From 0889ad38e5d1f6dcf6620b5189b1557c84193f6b Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 2 Oct 2024 22:43:37 +0100 Subject: [PATCH 24/45] (error): CirclesErrorNoArgs <- 1: CirclesArrayMustNotBeEmpty --- src/errors/Errors.sol | 4 +++- src/hub/Hub.sol | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index bdbaa10..0331c1f 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -6,6 +6,7 @@ interface ICirclesCompactErrors { * @dev CirclesErrorNoArgs is a generic error that does not require any arguments. * errorId: * 0: CirclesAddressCannotBeZero + * 1: CirclesArrayMustNotBeEmpty */ error CirclesErrorNoArgs(uint8 errorId, uint8 occuranceCode); } @@ -70,7 +71,8 @@ interface ICirclesErrors { error CirclesArraysLengthMismatch(uint256 lengthArray1, uint256 lengthArray2, uint8 code); - error CirclesArrayMustNotBeEmpty(uint8 code); + // CirclesErrorNoArgs 1 + // error CirclesArrayMustNotBeEmpty(uint8 code); error CirclesAmountMustNotBeZero(uint8 code); diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index e6a081c..f11609e 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -685,7 +685,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } if (_collateral.length == 0) { // At least one collateral must be provided. - revert CirclesArrayMustNotBeEmpty(0); + // revert CirclesArrayMustNotBeEmpty(0); + revert CirclesErrorNoArgs(1, 0); } if (!isGroup(_group)) { // Group is not registered as an avatar. From 2fdacd7f6635cbe72e7be8281961d54cc3ab5131 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 2 Oct 2024 23:14:38 +0100 Subject: [PATCH 25/45] (errors): adopt hex error code to reduce code size --- src/errors/Errors.sol | 39 +++++++++++++++++++++++++++---- src/hub/Hub.sol | 13 ++++++----- src/lift/DemurrageCircles.sol | 6 ++--- src/lift/ERC20Lift.sol | 8 +++---- src/lift/InflationaryCircles.sol | 6 ++--- src/migration/Migration.sol | 6 ++--- src/names/NameRegistry.sol | 2 +- src/operators/BaseOperator.sol | 2 +- src/treasury/StandardTreasury.sol | 4 ++-- src/treasury/StandardVault.sol | 2 +- 10 files changed, 60 insertions(+), 28 deletions(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 0331c1f..c30bf30 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -1,14 +1,44 @@ // 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. * errorId: - * 0: CirclesAddressCannotBeZero - * 1: CirclesArrayMustNotBeEmpty + * 0: 0x00 -> 0x1F CirclesAddressCannotBeZero + * 1: 0x20 -> 0x3F CirclesArrayMustNotBeEmpty + * 2: 0x40 -> 0x5F CirclesAmountMustNotBeZero */ - error CirclesErrorNoArgs(uint8 errorId, uint8 occuranceCode); + error CirclesErrorNoArgs(bytes1); } interface IHubErrors { @@ -74,7 +104,8 @@ interface ICirclesErrors { // CirclesErrorNoArgs 1 // error CirclesArrayMustNotBeEmpty(uint8 code); - error CirclesAmountMustNotBeZero(uint8 code); + // CirclesErrorNoArgs 2 + // error CirclesAmountMustNotBeZero(uint8 code); error CirclesProxyAlreadyInitialized(); diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index f11609e..99075fe 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -183,11 +183,11 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { ) Circles(_inflationDayZero, _gatewayUrl) { if (address(_hubV1) == address(0)) { // revert CirclesAddressCannotBeZero(0); - revert CirclesErrorNoArgs(0, 0); + revert CirclesErrorNoArgs(0x00); } if (_standardTreasury == address(0)) { // revert CirclesAddressCannotBeZero(1); - revert CirclesErrorNoArgs(0, 1); + revert CirclesErrorNoArgs(0x01); } // initialize linked list for avatars @@ -686,7 +686,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { if (_collateral.length == 0) { // At least one collateral must be provided. // revert CirclesArrayMustNotBeEmpty(0); - revert CirclesErrorNoArgs(1, 0); + revert CirclesErrorNoArgs(0x20); } if (!isGroup(_group)) { // Group is not registered as an avatar. @@ -712,7 +712,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { if (_amounts[i] == 0) { // Non-zero collateral must be provided. - revert CirclesAmountMustNotBeZero(0); + // revert CirclesAmountMustNotBeZero(0); + revert CirclesErrorNoArgs(0x40); } sumAmounts += _amounts[i]; } @@ -1020,13 +1021,13 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { if (_mint == address(0)) { // Mint address can not be zero. // revert CirclesAddressCannotBeZero(2); - revert CirclesErrorNoArgs(0, 2); + revert CirclesErrorNoArgs(0x02); } // 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(0, 3); + revert CirclesErrorNoArgs(0x03); } if (!nameRegistry.isValidName(_name)) { // Invalid group name. diff --git a/src/lift/DemurrageCircles.sol b/src/lift/DemurrageCircles.sol index 9803526..69d7fd1 100644 --- a/src/lift/DemurrageCircles.sol +++ b/src/lift/DemurrageCircles.sol @@ -47,16 +47,16 @@ contract DemurrageCircles is MasterCopyNonUpgradable, ERC20DiscountedBalances, E } if (address(_hub) == address(0)) { // revert CirclesAddressCannotBeZero(0); - revert CirclesErrorNoArgs(0, 4); + revert CirclesErrorNoArgs(0x04); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. // revert CirclesAddressCannotBeZero(1); - revert CirclesErrorNoArgs(0, 5); + revert CirclesErrorNoArgs(0x05); } if (_avatar == address(0)) { // revert CirclesAddressCannotBeZero(2); - revert CirclesErrorNoArgs(0, 6); + revert CirclesErrorNoArgs(0x06); } hub = IHubV2(_hub); avatar = _avatar; diff --git a/src/lift/ERC20Lift.sol b/src/lift/ERC20Lift.sol index 8f705e0..517a25c 100644 --- a/src/lift/ERC20Lift.sol +++ b/src/lift/ERC20Lift.sol @@ -41,22 +41,22 @@ contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors, ICirclesCompactE if (address(_hub) == address(0)) { // Must not be the zero address. // revert CirclesAddressCannotBeZero(0); - revert CirclesErrorNoArgs(0, 7); + revert CirclesErrorNoArgs(0x07); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. // revert CirclesAddressCannotBeZero(1); - revert CirclesErrorNoArgs(0, 8); + revert CirclesErrorNoArgs(0x08); } if (_masterCopyERC20Demurrage == address(0)) { // Must not be the zero address. // revert CirclesAddressCannotBeZero(3); - revert CirclesErrorNoArgs(0, 9); + revert CirclesErrorNoArgs(0x09); } if (_masterCopyERC20Inflation == address(0)) { // Must not be the zero address. // revert CirclesAddressCannotBeZero(4); - revert CirclesErrorNoArgs(0, 10); + revert CirclesErrorNoArgs(0x0A); } hub = _hub; diff --git a/src/lift/InflationaryCircles.sol b/src/lift/InflationaryCircles.sol index f8cc734..30dd8ea 100644 --- a/src/lift/InflationaryCircles.sol +++ b/src/lift/InflationaryCircles.sol @@ -53,17 +53,17 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc if (address(_hub) == address(0)) { // Must not be the zero address. // revert CirclesAddressCannotBeZero(0); - revert CirclesErrorNoArgs(0, 11); + revert CirclesErrorNoArgs(0x0B); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. // revert CirclesAddressCannotBeZero(1); - revert CirclesErrorNoArgs(0, 12); + revert CirclesErrorNoArgs(0x0C); } if (_avatar == address(0)) { // Must not be the zero address. // revert CirclesAddressCannotBeZero(2); - revert CirclesErrorNoArgs(0, 13); + revert CirclesErrorNoArgs(0x0D); } hub = IHubV2(_hub); avatar = _avatar; diff --git a/src/migration/Migration.sol b/src/migration/Migration.sol index f634424..e9e83ad 100644 --- a/src/migration/Migration.sol +++ b/src/migration/Migration.sol @@ -33,12 +33,12 @@ contract Migration is ICirclesErrors, IMigrationErrors, ICirclesCompactErrors { if (address(_hubV1) == address(0)) { // Hub v1 address can not be zero. // revert CirclesAddressCannotBeZero(0); - revert CirclesErrorNoArgs(0, 14); + revert CirclesErrorNoArgs(0x0E); } if (address(_hubV2) == address(0)) { // Hub v2 address can not be zero. // revert CirclesAddressCannotBeZero(1); - revert CirclesErrorNoArgs(0, 15); + revert CirclesErrorNoArgs(0x0F); } hubV1 = _hubV1; @@ -76,7 +76,7 @@ contract Migration is ICirclesErrors, IMigrationErrors, ICirclesCompactErrors { if (address(circlesV1) == address(0)) { // Invalid avatar, not registered in hub V1. // revert CirclesAddressCannotBeZero(2); - revert CirclesErrorNoArgs(0, 16); + revert CirclesErrorNoArgs(0x10); } if (_amounts[i] == 0) { // Amount must be greater than zero. diff --git a/src/names/NameRegistry.sol b/src/names/NameRegistry.sol index 0da2178..e1d446f 100644 --- a/src/names/NameRegistry.sol +++ b/src/names/NameRegistry.sol @@ -76,7 +76,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC if (address(_hub) == address(0)) { // Hub cannot be the zero address. // revert CirclesAddressCannotBeZero(0); - revert CirclesErrorNoArgs(0, 17); + revert CirclesErrorNoArgs(0x11); } hub = _hub; } diff --git a/src/operators/BaseOperator.sol b/src/operators/BaseOperator.sol index 5dc6f60..0a73038 100644 --- a/src/operators/BaseOperator.sol +++ b/src/operators/BaseOperator.sol @@ -15,7 +15,7 @@ contract BaseOperator is ICirclesErrors, ICirclesCompactErrors { if (address(_hub) == address(0)) { // Must not be the zero address. // revert CirclesAddressCannotBeZero(0); - revert CirclesErrorNoArgs(0, 18); + revert CirclesErrorNoArgs(0x12); } hub = _hub; diff --git a/src/treasury/StandardTreasury.sol b/src/treasury/StandardTreasury.sol index 0bd5207..f542fa9 100644 --- a/src/treasury/StandardTreasury.sol +++ b/src/treasury/StandardTreasury.sol @@ -81,12 +81,12 @@ contract StandardTreasury is if (address(_hub) == address(0)) { // Hub address cannot be 0 // revert CirclesAddressCannotBeZero(0); - revert CirclesErrorNoArgs(0, 19); + revert CirclesErrorNoArgs(0x13); } if (_mastercopyStandardVault == address(0)) { // Mastercopy standard vault address cannot be 0 // revert CirclesAddressCannotBeZero(1); - revert CirclesErrorNoArgs(0, 20); + revert CirclesErrorNoArgs(0x14); } hub = _hub; mastercopyStandardVault = _mastercopyStandardVault; diff --git a/src/treasury/StandardVault.sol b/src/treasury/StandardVault.sol index 475a596..7000f45 100644 --- a/src/treasury/StandardVault.sol +++ b/src/treasury/StandardVault.sol @@ -81,7 +81,7 @@ contract StandardVault is if (_receiver == address(0)) { // Vault: receiver cannot be 0 address // revert CirclesAddressCannotBeZero(0); - revert CirclesErrorNoArgs(0, 21); + revert CirclesErrorNoArgs(0x15); } // return the collateral to the receiver From caaca32843e2bbb61f91fc940a75b573f2b92e14 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 2 Oct 2024 23:22:48 +0100 Subject: [PATCH 26/45] (errors): uint8 conversion saves compile size... who knew? --- src/errors/Errors.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index c30bf30..5cf015b 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -33,12 +33,12 @@ pragma solidity >=0.8.24; interface ICirclesCompactErrors { /** * @dev CirclesErrorNoArgs is a generic error that does not require any arguments. - * errorId: + * error type: * 0: 0x00 -> 0x1F CirclesAddressCannotBeZero * 1: 0x20 -> 0x3F CirclesArrayMustNotBeEmpty * 2: 0x40 -> 0x5F CirclesAmountMustNotBeZero */ - error CirclesErrorNoArgs(bytes1); + error CirclesErrorNoArgs(uint8); } interface IHubErrors { From eb5ae88e91449401ede5c5e1677544d88533c6f1 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 2 Oct 2024 23:59:00 +0100 Subject: [PATCH 27/45] (errors): first signs of nett benefit --- src/circles/Circles.sol | 3 ++- src/errors/Errors.sol | 18 +++++++++++++++--- src/hub/Hub.sol | 30 +++++++++++++++++++----------- src/treasury/StandardTreasury.sol | 3 ++- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index c1d1716..b3ebee9 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -193,7 +193,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); diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 5cf015b..5281542 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -37,8 +37,17 @@ interface ICirclesCompactErrors { * 0: 0x00 -> 0x1F CirclesAddressCannotBeZero * 1: 0x20 -> 0x3F CirclesArrayMustNotBeEmpty * 2: 0x40 -> 0x5F CirclesAmountMustNotBeZero + * 3: 0x60 -> 0x7F CirclesHubFlowVerticesMustBeSorted + * 4: 0x80 -> 0x9F CirclesLogicAssertion */ error CirclesErrorNoArgs(uint8); + + /** + * @dev CirclesErrorOneAddressArg is a generic error that requires one address argument. + * error type: + * 0: 0x00 -> 0x1F CirclesHubMustBeHuman(avatar) + */ + error CirclesErrorOneAddressArg(address, uint8); } interface IHubErrors { @@ -46,7 +55,8 @@ interface IHubErrors { 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); @@ -62,7 +72,8 @@ interface IHubErrors { error CirclesHubFlowEdgeIsNotPermitted(address receiver, uint256 circlesId, uint8 code); - error CirclesHubFlowVerticesMustBeSorted(); + // CirclesErrorNoArgs 3 + // error CirclesHubFlowVerticesMustBeSorted(); error CirclesHubFlowEdgeStreamMismatch(uint16 flowEdgeId, uint16 streamId, uint8 code); @@ -109,7 +120,8 @@ interface ICirclesErrors { error CirclesProxyAlreadyInitialized(); - error CirclesLogicAssertion(uint8 code); + // CirclesErrorNoArgs 4 + // error CirclesLogicAssertion(uint8 code); error CirclesIdMustBeDerivedFromAddress(uint256 providedId, uint8 code); diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 99075fe..7ceaed1 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -248,7 +248,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // 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); + // revert CirclesHubMustBeHuman(msg.sender, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0x00); } if (!isTrusted(_inviter, msg.sender)) { @@ -375,7 +376,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); @@ -442,7 +444,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 @@ -463,7 +466,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); @@ -498,7 +502,8 @@ 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); } @@ -777,7 +782,8 @@ 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. @@ -1065,7 +1071,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); } } } @@ -1126,7 +1133,8 @@ 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 @@ -1199,9 +1207,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)) revert CirclesErrorNoArgs(0x81); // CirclesLogicAssertion(1); + if (_trusted == address(0)) revert CirclesErrorNoArgs(0x82); // CirclesLogicAssertion(2); + if (_trusted == SENTINEL) revert CirclesErrorNoArgs(0x83); // CirclesLogicAssertion(3); TrustMarker storage sentinelMarker = trustMarkers[_truster][SENTINEL]; if (sentinelMarker.previous == address(0)) { diff --git a/src/treasury/StandardTreasury.sol b/src/treasury/StandardTreasury.sol index f542fa9..7851742 100644 --- a/src/treasury/StandardTreasury.sol +++ b/src/treasury/StandardTreasury.sol @@ -194,7 +194,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 From 3d8323b33ff5b84b3a664063db35ac46cf3f74eb Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 3 Oct 2024 17:44:36 +0100 Subject: [PATCH 28/45] (errors): continue replacing errors, but only limited benefit so far --- src/errors/Errors.sol | 20 ++++++++++++----- src/hub/Hub.sol | 51 ++++++++++++++++++++++++++---------------- src/lift/ERC20Lift.sol | 3 ++- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 5281542..060b710 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -46,21 +46,30 @@ interface ICirclesCompactErrors { * @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) */ error CirclesErrorOneAddressArg(address, 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); // 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 @@ -95,7 +104,8 @@ interface ICirclesDemurrageErrors { } interface ICirclesErrors { - error CirclesAvatarMustBeRegistered(address avatar, uint8 code); + // CirclesErrorOneAddressArg 1 + // error CirclesAvatarMustBeRegistered(address avatar, uint8 code); // CirclesErrorNoArgs 0 // error CirclesAddressCannotBeZero(uint8 code); diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 7ceaed1..d4cc635 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -237,11 +237,13 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { (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); + // revert CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(msg.sender, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0x60); } // if it has been stopped, did it stop before the end of the invitation period? if (v1LastTouched >= invitationOnlyTime) { - revert CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(msg.sender, 1); + // revert CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(msg.sender, 1); + revert CirclesErrorOneAddressArg(msg.sender, 0x61); } } else { // if someone has invited you by trusting your address ahead of this call, @@ -253,7 +255,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } if (!isTrusted(_inviter, msg.sender)) { - revert CirclesHubInvalidTrustReceiver(msg.sender, 0); + // revert CirclesHubInvalidTrustReceiver(msg.sender, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0xA0); } // register the invited human; reverts if they already exist @@ -353,18 +356,21 @@ 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)) { + // // revert CirclesAvatarMustBeRegistered(msg.sender, 0); + // revert CirclesErrorOneAddressArg(msg.sender, 0x20); + // } + 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); @@ -487,7 +493,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function migrate(address _owner, address[] calldata _avatars, uint256[] calldata _amounts) external onlyMigration { if (avatars[_owner] == address(0)) { // Only registered avatars can migrate v1 tokens. - revert CirclesAvatarMustBeRegistered(_owner, 1); + // revert CirclesAvatarMustBeRegistered(_owner, 1); + revert CirclesErrorOneAddressArg(_owner, 0x21); } if (_avatars.length != _amounts.length) { revert CirclesArraysLengthMismatch(_avatars.length, _amounts.length, 0); @@ -541,7 +548,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, ""); @@ -591,7 +599,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; @@ -695,7 +704,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } 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, @@ -787,14 +797,16 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } 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); } } @@ -1154,7 +1166,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; diff --git a/src/lift/ERC20Lift.sol b/src/lift/ERC20Lift.sol index 517a25c..d3ccd25 100644 --- a/src/lift/ERC20Lift.sol +++ b/src/lift/ERC20Lift.sol @@ -81,7 +81,8 @@ contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors, ICirclesCompactE // 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 CirclesAvatarMustBeRegistered(_avatar, 0); + revert CirclesErrorOneAddressArg(_avatar, 0x26); } } From 353601dd035d3f0bf152f349b28fceda1efb07de Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 3 Oct 2024 18:24:06 +0100 Subject: [PATCH 29/45] (errors): churning along, also starting to reduce some params in advanced errors --- src/circles/Circles.sol | 3 ++- src/errors/Errors.sol | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index b3ebee9..30ccc05 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -82,7 +82,8 @@ 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); } // Early check for stopped mints diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 060b710..cac6fd3 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -51,6 +51,7 @@ interface ICirclesCompactErrors { * 3: 0x60 -> 0x7F CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(avatar) * 4: 0x80 -> 0x9F CirclesHubAvatarAlreadyRegistered(avatar) * 5: 0xA0 -> 0xBF CirclesHubInvalidTrustReceiver(trustReceiver) + * 6: 0xC0 -> 0xDF CirclesERC1155MintBlocked(human, ~mintV1Status~) */ error CirclesErrorOneAddressArg(address, uint8); } @@ -92,7 +93,8 @@ interface IHubErrors { } 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); From 7e4fbe3b17c7c53bf762526e8e69452377a7cf1d Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 3 Oct 2024 18:26:26 +0100 Subject: [PATCH 30/45] (circles): start collapsing if-statements of separate condition checks into one to save code size --- src/circles/Circles.sol | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 30ccc05..6b67c34 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -86,17 +86,12 @@ contract Circles is ERC1155, ICirclesErrors { revert CirclesErrorOneAddressArg(_human, 0xC0); } - // Early check for stopped mints - if (mintTime.lastMintTime == INDEFINITE_FUTURE) { - return (0, 0, 0); - } - // 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) { - // No new completed hour to mint + if (lastCompletedHour >= currentCompletedHour || mintTime.lastMintTime == INDEFINITE_FUTURE) { + // No new completed hour to mint, or stopped return (0, 0, 0); } From 1135f83ec492ca340290945f501888915e313823 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 3 Oct 2024 19:38:02 +0100 Subject: [PATCH 31/45] (errors): reduce error detail on RejectBurn by mint policy --- src/errors/Errors.sol | 18 +++++++++++++++--- src/hub/Hub.sol | 16 ++++++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index cac6fd3..efc3259 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -54,6 +54,15 @@ interface ICirclesCompactErrors { * 6: 0xC0 -> 0xDF CirclesERC1155MintBlocked(human, ~mintV1Status~) */ 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)) + */ + error CirclesErrorAddressUintArgs(address, uint256, uint8); } interface IHubErrors { @@ -76,11 +85,14 @@ interface IHubErrors { 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 streamIndex, 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); // CirclesErrorNoArgs 3 // error CirclesHubFlowVerticesMustBeSorted(); diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index d4cc635..f1d75d8 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -539,7 +539,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); @@ -570,9 +571,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); } } @@ -722,7 +724,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { if (!isValidCollateral) { // Group does not trust collateral, or flow edge is not permitted - revert CirclesHubFlowEdgeIsNotPermitted(_group, _collateral[i], 0); + // revert CirclesHubFlowEdgeIsNotPermitted(_group, _collateral[i], 0); + revert CirclesErrorAddressUintArgs(_group, _collateral[i], 0x20); } if (_amounts[i] == 0) { @@ -827,7 +830,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 From 98d9af38c0de13c4126ff4366d0eb8d35b7177c9 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 3 Oct 2024 19:47:14 +0100 Subject: [PATCH 32/45] (errors): repeat the trick! another 80 bytes down --- src/errors/Errors.sol | 8 +++++--- src/hub/Hub.sol | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index efc3259..13bbd7f 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -61,6 +61,7 @@ interface ICirclesCompactErrors { * 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) */ error CirclesErrorAddressUintArgs(address, uint256, uint8); } @@ -81,9 +82,10 @@ interface IHubErrors { // 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 + // ); // CirclesErrorAddressUintArgs 2 // error CirclesHubGroupMintPolicyRejectedBurn(address burner, address group, uint256 amount, bytes data, uint8 code); diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index f1d75d8..a9f679d 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -739,7 +739,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // 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 From 7025fef50af43dbed129c95536e846de443e493e Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 3 Oct 2024 20:39:03 +0100 Subject: [PATCH 33/45] (errors): covering more green territory --- src/circles/Circles.sol | 3 ++- src/circles/DiscountedBalances.sol | 12 ++++++++---- src/errors/Errors.sol | 14 +++++++++----- src/hub/Hub.sol | 16 +++++----------- src/lift/ERC20DiscountedBalances.sol | 20 ++++++++++++-------- 5 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 6b67c34..1b36614 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -168,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; 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/errors/Errors.sol b/src/errors/Errors.sol index 13bbd7f..9cd178e 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -62,6 +62,8 @@ interface ICirclesCompactErrors { * 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); } @@ -101,7 +103,7 @@ interface IHubErrors { 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); } @@ -110,11 +112,13 @@ interface ICirclesDemurrageErrors { // 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); } diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index a9f679d..48f5250 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -889,11 +889,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); } } @@ -925,13 +923,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); } } } 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; From 320a002a97adffc18489aa9393bdd6f4c026bdbb Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 3 Oct 2024 21:14:26 +0100 Subject: [PATCH 34/45] (errors): simplify revert cases in registerGroup --- src/hub/Hub.sol | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 48f5250..2300d0a 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -1034,27 +1034,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); - revert CirclesErrorNoArgs(0x02); - } - // 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(0x03); + 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 From 8f46b3654ddb605dbe77d2023570a66ee7c46af3 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Fri, 4 Oct 2024 19:06:23 +0100 Subject: [PATCH 35/45] (errors): further compaction of errors, esp relevant for hub --- src/errors/Errors.sol | 4 +++- src/hub/Hub.sol | 3 ++- src/lift/DemurrageCircles.sol | 7 ++++--- src/lift/InflationaryCircles.sol | 7 ++++--- src/names/NameRegistry.sol | 9 +++++---- src/operators/SignedPathOperator.sol | 3 ++- src/treasury/StandardTreasury.sol | 9 +++++---- src/treasury/StandardVault.sol | 3 ++- 8 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 9cd178e..ee67e00 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -52,6 +52,7 @@ interface ICirclesCompactErrors { * 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); @@ -130,7 +131,8 @@ interface ICirclesErrors { // 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); diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 2300d0a..7c820c7 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -138,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); } _; } diff --git a/src/lift/DemurrageCircles.sol b/src/lift/DemurrageCircles.sol index 69d7fd1..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); } _; } @@ -100,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); @@ -117,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/InflationaryCircles.sol b/src/lift/InflationaryCircles.sol index 30dd8ea..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); } _; } @@ -106,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); @@ -122,7 +123,7 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc public view override - onlyHub(1) + onlyHub(0xE4) returns (bytes4) { revert CirclesERC1155CannotReceiveBatch(0); diff --git a/src/names/NameRegistry.sol b/src/names/NameRegistry.sol index e1d446f..2e0f5f9 100644 --- a/src/names/NameRegistry.sol +++ b/src/names/NameRegistry.sol @@ -65,7 +65,8 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC 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); } _; } @@ -98,7 +99,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC _registerShortNameWithNonce(_nonce); } - function setMetadataDigest(address _avatar, bytes32 _metadataDigest) external onlyHub(0) { + function setMetadataDigest(address _avatar, bytes32 _metadataDigest) external onlyHub(0xE5) { _setMetadataDigest(_avatar, _metadataDigest); } @@ -106,7 +107,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC _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; @@ -117,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; 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 7851742..081bbe5 100644 --- a/src/treasury/StandardTreasury.sol +++ b/src/treasury/StandardTreasury.sol @@ -62,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); } _; } @@ -108,7 +109,7 @@ 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); @@ -132,7 +133,7 @@ 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 _lockCollateralBatchGroupCircles(_ids, _values, group, userData); diff --git a/src/treasury/StandardVault.sol b/src/treasury/StandardVault.sol index 7000f45..df31728 100644 --- a/src/treasury/StandardVault.sol +++ b/src/treasury/StandardVault.sol @@ -34,7 +34,8 @@ contract StandardVault is 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); } _; } From e28ef69f3022214a8e5bb2c0f5d8c6ce314e70c2 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Fri, 4 Oct 2024 19:27:00 +0100 Subject: [PATCH 36/45] (errors): compact errors --- src/errors/Errors.sol | 6 +++--- src/hub/Hub.sol | 21 ++++++++++++++------- src/migration/Migration.sol | 3 ++- src/treasury/StandardVault.sol | 3 ++- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index ee67e00..9d3b1d2 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -39,6 +39,7 @@ interface ICirclesCompactErrors { * 2: 0x40 -> 0x5F CirclesAmountMustNotBeZero * 3: 0x60 -> 0x7F CirclesHubFlowVerticesMustBeSorted * 4: 0x80 -> 0x9F CirclesLogicAssertion + * 5: 0xA0 -> 0xBF CirclesArraysLengthMismatch */ error CirclesErrorNoArgs(uint8); @@ -136,13 +137,12 @@ interface ICirclesErrors { 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); // CirclesErrorNoArgs 1 // error CirclesArrayMustNotBeEmpty(uint8 code); diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 7c820c7..8fd5039 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -498,7 +498,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { revert CirclesErrorOneAddressArg(_owner, 0x21); } if (_avatars.length != _amounts.length) { - revert CirclesArraysLengthMismatch(_avatars.length, _amounts.length, 0); + // revert CirclesArraysLengthMismatch(_avatars.length, _amounts.length, 0); + revert CirclesErrorNoArgs(0xA0); } // register all unregistered avatars as humans, and check that registered avatars are humans @@ -698,7 +699,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { ) internal { if (_collateral.length != _amounts.length) { // Collateral and amount arrays must have equal length. - revert CirclesArraysLengthMismatch(_collateral.length, _amounts.length, 1); + // revert CirclesArraysLengthMismatch(_collateral.length, _amounts.length, 1); + revert CirclesErrorNoArgs(0xA1); } if (_collateral.length == 0) { // At least one collateral must be provided. @@ -778,15 +780,18 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { ) internal view returns (int256[] memory) { if (3 * _flow.length != _coordinates.length) { // Mismatch in flow and coordinates length. - revert CirclesArraysLengthMismatch(_flow.length, _coordinates.length, 2); + // revert CirclesArraysLengthMismatch(_flow.length, _coordinates.length, 2); + revert CirclesErrorNoArgs(0xA2); } if (_flowVertices.length > type(uint16).max) { // Too many vertices. - revert CirclesArraysLengthMismatch(_flowVertices.length, type(uint16).max, 3); + // revert CirclesArraysLengthMismatch(_flowVertices.length, type(uint16).max, 3); + revert CirclesErrorNoArgs(0xA3); } if (_flowVertices.length == 0 || _flow.length == 0) { // Empty flow matrix - revert CirclesArraysLengthMismatch(_flowVertices.length, _flow.length, 4); + // revert CirclesArraysLengthMismatch(_flowVertices.length, _flow.length, 4); + revert CirclesErrorNoArgs(0xA4); } // initialize the netted flow array @@ -985,7 +990,8 @@ 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]) { @@ -1185,7 +1191,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); diff --git a/src/migration/Migration.sol b/src/migration/Migration.sol index e9e83ad..94776ff 100644 --- a/src/migration/Migration.sol +++ b/src/migration/Migration.sol @@ -66,7 +66,8 @@ contract Migration is ICirclesErrors, IMigrationErrors, ICirclesCompactErrors { 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); diff --git a/src/treasury/StandardVault.sol b/src/treasury/StandardVault.sol index df31728..049473c 100644 --- a/src/treasury/StandardVault.sol +++ b/src/treasury/StandardVault.sol @@ -101,7 +101,8 @@ contract StandardVault is { 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 From b94d28e5c15018b6a32d9a5a5f55aef421458c24 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Fri, 4 Oct 2024 19:32:45 +0100 Subject: [PATCH 37/45] (hub): collapsing if-cond in upsert avatar --- src/hub/Hub.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 8fd5039..878aae2 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -1215,9 +1215,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 CirclesErrorNoArgs(0x81); // CirclesLogicAssertion(1); - if (_trusted == address(0)) revert CirclesErrorNoArgs(0x82); // CirclesLogicAssertion(2); - if (_trusted == SENTINEL) revert CirclesErrorNoArgs(0x83); // 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)) { From 9143ed7c2b54589638a5efebf96f278b4cabac76 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Fri, 4 Oct 2024 19:55:32 +0100 Subject: [PATCH 38/45] (hub): more collapsing if clauses --- src/errors/Errors.sol | 2 +- src/hub/Hub.sol | 33 +++++++++------------------------ 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 9d3b1d2..ce5ef4c 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -35,7 +35,7 @@ interface ICirclesCompactErrors { * @dev CirclesErrorNoArgs is a generic error that does not require any arguments. * error type: * 0: 0x00 -> 0x1F CirclesAddressCannotBeZero - * 1: 0x20 -> 0x3F CirclesArrayMustNotBeEmpty + * 1: 0x20 -> 0x3F CirclesArrayMustNotBeEmpty (no occurances anymore; freed up) * 2: 0x40 -> 0x5F CirclesAmountMustNotBeZero * 3: 0x60 -> 0x7F CirclesHubFlowVerticesMustBeSorted * 4: 0x80 -> 0x9F CirclesLogicAssertion diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 878aae2..f56edd8 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -697,16 +697,12 @@ 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. + // At least one collateral must be provided. // revert CirclesArraysLengthMismatch(_collateral.length, _amounts.length, 1); revert CirclesErrorNoArgs(0xA1); } - if (_collateral.length == 0) { - // At least one collateral must be provided. - // revert CirclesArrayMustNotBeEmpty(0); - revert CirclesErrorNoArgs(0x20); - } if (!isGroup(_group)) { // Group is not registered as an avatar. // revert CirclesHubGroupIsNotRegistered(_group, 0); @@ -725,17 +721,13 @@ 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 + // Non-zero collateral must be provided. // revert CirclesHubFlowEdgeIsNotPermitted(_group, _collateral[i], 0); revert CirclesErrorAddressUintArgs(_group, _collateral[i], 0x20); } - if (_amounts[i] == 0) { - // Non-zero collateral must be provided. - // revert CirclesAmountMustNotBeZero(0); - revert CirclesErrorNoArgs(0x40); - } sumAmounts += _amounts[i]; } @@ -778,21 +770,14 @@ 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. + 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); } - if (_flowVertices.length > type(uint16).max) { - // Too many vertices. - // revert CirclesArraysLengthMismatch(_flowVertices.length, type(uint16).max, 3); - revert CirclesErrorNoArgs(0xA3); - } - if (_flowVertices.length == 0 || _flow.length == 0) { - // Empty flow matrix - // revert CirclesArraysLengthMismatch(_flowVertices.length, _flow.length, 4); - revert CirclesErrorNoArgs(0xA4); - } // initialize the netted flow array int256[] memory nettedFlow = new int256[](_flowVertices.length); From 8c703d00fcc336200e0da5470b0144980701d0bf Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Fri, 4 Oct 2024 21:19:37 +0100 Subject: [PATCH 39/45] (hub): more if collapsing --- src/hub/Hub.sol | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index f56edd8..de93498 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -237,27 +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) { + // 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); } - // if it has been stopped, did it stop before the end of the invitation period? - if (v1LastTouched >= invitationOnlyTime) { - // revert CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(msg.sender, 1); - revert CirclesErrorOneAddressArg(msg.sender, 0x61); - } } 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)) { + if (!isHuman(_inviter) || !isTrusted(_inviter, msg.sender)) { // revert CirclesHubMustBeHuman(msg.sender, 0); - revert CirclesErrorOneAddressArg(msg.sender, 0x00); - } - - if (!isTrusted(_inviter, msg.sender)) { // revert CirclesHubInvalidTrustReceiver(msg.sender, 0); - revert CirclesErrorOneAddressArg(msg.sender, 0xA0); + revert CirclesErrorOneAddressArg(_inviter, 0xA0); } // register the invited human; reverts if they already exist @@ -357,10 +349,6 @@ 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); - // revert CirclesErrorOneAddressArg(msg.sender, 0x20); - // } if ( avatars[msg.sender] == address(0) || _trustReceiver == address(0) || _trustReceiver == SENTINEL || _trustReceiver == msg.sender @@ -492,15 +480,13 @@ 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. + // 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); } - if (_avatars.length != _amounts.length) { - // revert CirclesArraysLengthMismatch(_avatars.length, _amounts.length, 0); - revert CirclesErrorNoArgs(0xA0); - } // register all unregistered avatars as humans, and check that registered avatars are humans // after the bootstrap period, the _owner needs to pay the equivalent invitation cost for all newly registered humans From 1f7c24d74befde5ef751657ed4cad72e7ba4d2c5 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Sat, 5 Oct 2024 21:30:38 +0100 Subject: [PATCH 40/45] (hub): extend RegisterHuman event with inviter data --- src/hub/Hub.sol | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index de93498..5763137 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -113,7 +113,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // Events - event RegisterHuman(address indexed avatar); + event RegisterHuman(address indexed avatar, address indexed inviter); event RegisterOrganization(address indexed organization, string name); event RegisterGroup( address indexed group, address indexed mint, address indexed treasury, string name, string symbol @@ -235,7 +235,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // leave the inviter address as zero. // only available for v1 users with stopped v1 mint, for initial bootstrap period - (address v1CirclesStatus, uint256 v1LastTouched) = _registerHuman(msg.sender); + (address v1CirclesStatus, uint256 v1LastTouched) = _registerHuman(msg.sender, _inviter); // check if v1 Circles exists and has been stopped // and if it has been stopped, did it stop before the end of the invitation period? if (v1CirclesStatus != CIRCLES_STOPPED_V1 || v1LastTouched >= invitationOnlyTime) { @@ -256,7 +256,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // it checks the status of the avatar in v1, but regardless of the status // we can proceed to register the avatar in v2 (they might not be able to mint yet // if they have not stopped their v1 contract) - _registerHuman(msg.sender); + _registerHuman(msg.sender, _inviter); if (block.timestamp > invitationOnlyTime) { // after the invitation period, the inviter must burn the invitation cost @@ -490,7 +490,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // register all unregistered avatars as humans, and check that registered avatars are humans // after the bootstrap period, the _owner needs to pay the equivalent invitation cost for all newly registered humans - uint256 cost = INVITATION_COST * _ensureAvatarsRegistered(_avatars); + uint256 cost = INVITATION_COST * _ensureAvatarsRegistered(_owner, _avatars); // Invitation cost only applies after the bootstrap period if (block.timestamp > invitationOnlyTime && cost > 0) { @@ -978,7 +978,10 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * Additionally set the trust to self indefinitely. * @param _human address of the human to be registered */ - function _registerHuman(address _human) internal returns (address v1CirclesStatus, uint256 v1LastTouched) { + function _registerHuman(address _human, address _inviter) + internal + returns (address v1CirclesStatus, uint256 v1LastTouched) + { // insert avatar into linked list; reverts if it already exists _insertAvatar(_human); @@ -992,7 +995,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // trust self indefinitely, cannot be altered later _trust(_human, _human, INDEFINITE_FUTURE); - emit RegisterHuman(_human); + emit RegisterHuman(_human, _inviter); return (v1CirclesStatus, v1LastTouched); } @@ -1039,12 +1042,12 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { emit Trust(_truster, _trustee, _expiry); } - function _ensureAvatarsRegistered(address[] calldata _avatars) internal returns (uint256) { + function _ensureAvatarsRegistered(address _inviter, address[] calldata _avatars) internal returns (uint256) { uint256 registrationCount = 0; for (uint256 i = 0; i < _avatars.length; i++) { if (avatars[_avatars[i]] == address(0)) { registrationCount++; - _registerHuman(_avatars[i]); + _registerHuman(_avatars[i], _inviter); } else { if (!isHuman(_avatars[i])) { // Only humans can be registered. From 62908104522c289276ef2e5a0daebd0f62d4723f Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Sat, 5 Oct 2024 21:48:05 +0100 Subject: [PATCH 41/45] (hub): discount event and advanced usage flag set event --- src/circles/DiscountedBalances.sol | 5 +++++ src/circles/ERC1155.sol | 1 + src/hub/Hub.sol | 5 +++++ src/lift/ERC20DiscountedBalances.sol | 7 +++++++ 4 files changed, 18 insertions(+) diff --git a/src/circles/DiscountedBalances.sol b/src/circles/DiscountedBalances.sol index 418535c..75ce835 100644 --- a/src/circles/DiscountedBalances.sol +++ b/src/circles/DiscountedBalances.sol @@ -18,6 +18,10 @@ contract DiscountedBalances is Demurrage { */ mapping(uint256 => DiscountedBalance) internal discountedTotalSupplies; + // Events + + event DiscountCost(address indexed account, uint256 indexed id, uint256 discountCost); + // Constructor /** @@ -127,6 +131,7 @@ contract DiscountedBalances is Demurrage { uint256 discountCost = discountedBalance.balance - discountedBalanceOnDay; if (discountCost > 0) { emit IERC1155.TransferSingle(msg.sender, _account, address(0), _id, discountCost); + emit DiscountCost(_account, _id, discountCost); } } uint256 updatedBalance = discountedBalanceOnDay + _value; diff --git a/src/circles/ERC1155.sol b/src/circles/ERC1155.sol index 23f2a30..b0a2dba 100644 --- a/src/circles/ERC1155.sol +++ b/src/circles/ERC1155.sol @@ -174,6 +174,7 @@ abstract contract ERC1155 is DiscountedBalances, Context, ERC165, IERC1155, IERC } if (discountCost > 0) { emit TransferSingle(operator, from, address(0), id, discountCost); + emit DiscountCost(from, id, discountCost); } unchecked { // Overflow not possible: value <= fromBalance diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 5763137..a69cc3e 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -131,6 +131,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { address indexed sender, address indexed receiver, address indexed group, uint256[] collateral, uint256[] amounts ); + event SetAdvancedUsageFlag(address indexed avatar, bytes32 flag); + // Modifiers /** @@ -594,6 +596,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } advancedUsageFlags[msg.sender] = _flag; + + // emit event for setting the advanced usage flag + emit SetAdvancedUsageFlag(msg.sender, _flag); } // Public functions diff --git a/src/lift/ERC20DiscountedBalances.sol b/src/lift/ERC20DiscountedBalances.sol index 8bdc1ef..5b206e2 100644 --- a/src/lift/ERC20DiscountedBalances.sol +++ b/src/lift/ERC20DiscountedBalances.sol @@ -18,6 +18,10 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { */ mapping(address => DiscountedBalance) public discountedBalances; + // Events + + event DiscountCost(address indexed account, uint256 discountCost); + // Constructor // External functions @@ -133,6 +137,7 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { uint256 discountCost = discountedBalance.balance - discountedBalanceOnDay; if (discountCost > 0) { emit Transfer(_account, address(0), discountCost); + emit DiscountCost(_account, discountCost); } } uint256 updatedBalance = discountedBalanceOnDay + _value; @@ -154,6 +159,7 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { } if (discountCost > 0) { emit Transfer(_from, address(0), discountCost); + emit DiscountCost(_from, discountCost); } unchecked { _updateBalance(_from, fromBalance - _amount, day); @@ -176,6 +182,7 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { } if (discountCost > 0) { emit Transfer(_owner, address(0), discountCost); + emit DiscountCost(_owner, discountCost); } unchecked { _updateBalance(_owner, ownerBalance - _amount, day); From 4a98b0ed738f0dd52eee6870236bcf85f16fe31a Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Sun, 6 Oct 2024 12:20:36 +0100 Subject: [PATCH 42/45] (hub): scope effects of flow edge wit separator events --- src/hub/Hub.sol | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index a69cc3e..da4c524 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -123,6 +123,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { event Stopped(address indexed avatar); + event FlowEdgesScopeSingleStarted(uint256 indexed flowEdgeId, uint16 streamId); + event FlowEdgesScopeLastEnded(); event StreamCompleted( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); @@ -877,6 +879,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } } + emit FlowEdgesScopeSingleStarted(i, _flow[i].streamSinkId); + // effect the flow edge if (!isGroup(to)) { // do a erc1155 single transfer without acceptance check, @@ -903,6 +907,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { index = index + 3; } + emit FlowEdgesScopeLastEnded(); + // check that all streams are properly defined for (uint16 i = 0; i < _streams.length; i++) { if (streamReceivers[i] == address(0) || streamBatchCounter[i] != _streams[i].flowEdgeIds.length) { From 9d72d672c209208d4b1693462f37fb5a62c3a7c0 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 7 Oct 2024 12:01:54 +0100 Subject: [PATCH 43/45] (nameRegistry): register hub as Circles (CRC) in name registry --- src/names/NameRegistry.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/names/NameRegistry.sol b/src/names/NameRegistry.sol index 2e0f5f9..42cf604 100644 --- a/src/names/NameRegistry.sol +++ b/src/names/NameRegistry.sol @@ -80,6 +80,10 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC revert CirclesErrorNoArgs(0x11); } hub = _hub; + + // register the hub itself in the name registry + customNames[address(_hub)] = "Circles"; + customSymbols[address(_hub)] = "CRC"; } // External functions From b824758e79ab581278c0f17bd03bde7855161afc Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 7 Oct 2024 12:03:18 +0100 Subject: [PATCH 44/45] (version): update to rc-v0.3.7-alpha --- script/deployments/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/deployments/package.json b/script/deployments/package.json index 1ab192d..40b01f0 100644 --- a/script/deployments/package.json +++ b/script/deployments/package.json @@ -1,6 +1,6 @@ { "name": "deploy-circles", - "version": "rc-0.3.6-alpha", + "version": "rc-0.3.7-alpha", "type": "module", "dependencies": { "dotenv": "^16.4.5", From be6b97dd2e8abf115072c77bbd2968af01c1a686 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 7 Oct 2024 12:28:34 +0100 Subject: [PATCH 45/45] (deploy): artefacts of rc-v0.3.7-alpha --- ...ts-rc-0.3.7-alpha-b824758-241007-120349.txt | 9 +++++++++ ...do-rc-0.3.7-alpha-b824758-241007-120349.log | 18 ++++++++++++++++++ .../constructorArgs_BaseGroupMintPolicy.txt | 1 + .../constructorArgs_ERC20Lift.txt | 1 + .../constructorArgs_Hub.txt | 1 + ...onstructorArgs_MastercopyDemurrageERC20.txt | 1 + ...tructorArgs_MastercopyInflationaryERC20.txt | 1 + ...constructorArgs_MastercopyStandardVault.txt | 1 + .../constructorArgs_Migration.txt | 1 + .../constructorArgs_NameRegistry.txt | 1 + .../constructorArgs_StandardTreasury.txt | 1 + .../constructorArgs_BaseGroupMintPolicy.txt | 1 + .../constructorArgs_ERC20Lift.txt | 1 + .../constructorArgs_Hub.txt | 1 + ...onstructorArgs_MastercopyDemurrageERC20.txt | 1 + ...tructorArgs_MastercopyInflationaryERC20.txt | 1 + ...constructorArgs_MastercopyStandardVault.txt | 1 + .../constructorArgs_Migration.txt | 1 + .../constructorArgs_NameRegistry.txt | 1 + .../constructorArgs_StandardTreasury.txt | 1 + ...ts-rc-0.3.7-alpha-b824758-241007-121112.txt | 9 +++++++++ ...in-rc-0.3.7-alpha-b824758-241007-121112.log | 18 ++++++++++++++++++ 22 files changed, 72 insertions(+) create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-artefacts-rc-0.3.7-alpha-b824758-241007-120349.txt create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-rc-0.3.7-alpha-b824758-241007-120349.log create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_BaseGroupMintPolicy.txt create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_ERC20Lift.txt create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Hub.txt create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyDemurrageERC20.txt create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyInflationaryERC20.txt create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyStandardVault.txt create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Migration.txt create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_NameRegistry.txt create mode 100644 script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_StandardTreasury.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_BaseGroupMintPolicy.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_ERC20Lift.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Hub.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyDemurrageERC20.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyInflationaryERC20.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyStandardVault.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Migration.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_NameRegistry.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_StandardTreasury.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-artefacts-rc-0.3.7-alpha-b824758-241007-121112.txt create mode 100644 script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-rc-0.3.7-alpha-b824758-241007-121112.log diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-artefacts-rc-0.3.7-alpha-b824758-241007-120349.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-artefacts-rc-0.3.7-alpha-b824758-241007-120349.txt new file mode 100644 index 0000000..095422f --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-artefacts-rc-0.3.7-alpha-b824758-241007-120349.txt @@ -0,0 +1,9 @@ +{"contractName":"Hub","deployedAddress":"0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb","sourcePath":"src/hub/Hub.sol:Hub","constructor-args":"0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984 0xA8366F19208FaE17f3707f5164bDC3c73eea2219 0xC7E57f5356c46b53A2A1395766B90A5d57981eDf 0x86eA22F850F7fe97De700d841200e148347Ca231 1675209600 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json","argumentsFile":"constructorArgs_Hub.txt"} +{"contractName":"Migration","deployedAddress":"0xA8366F19208FaE17f3707f5164bDC3c73eea2219","sourcePath":"src/migration/Migration.sol:Migration","constructor-args":"0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 1675209600","argumentsFile":"constructorArgs_Migration.txt"} +{"contractName":"NameRegistry","deployedAddress":"0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984","sourcePath":"src/names/NameRegistry.sol:NameRegistry","constructor-args":"0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb","argumentsFile":"constructorArgs_NameRegistry.txt"} +{"contractName":"ERC20Lift","deployedAddress":"0xC7E57f5356c46b53A2A1395766B90A5d57981eDf","sourcePath":"src/lift/ERC20Lift.sol:ERC20Lift","constructor-args":"0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984 0xcB42B236c3e58857A7F3D45df427535976e09027 0x0d52CBB59F817f23861b4571F1c056e7E3FaC6cE","argumentsFile":"constructorArgs_ERC20Lift.txt"} +{"contractName":"StandardTreasury","deployedAddress":"0x86eA22F850F7fe97De700d841200e148347Ca231","sourcePath":"src/treasury/StandardTreasury.sol:StandardTreasury","constructor-args":"0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 0x7881Eca1d73a2Da217Ac206Ae281048BdA0E1a94","argumentsFile":"constructorArgs_StandardTreasury.txt"} +{"contractName":"BaseGroupMintPolicy","deployedAddress":"0x92bfAbDc2D2608751C617e48469278CF19ef3C77","sourcePath":"src/groups/BaseMintPolicy.sol:MintPolicy","constructor-args":"","argumentsFile":"constructorArgs_BaseGroupMintPolicy.txt"} +{"contractName":"MastercopyDemurrageERC20","deployedAddress":"0xcB42B236c3e58857A7F3D45df427535976e09027","sourcePath":"src/lift/DemurrageCircles.sol:DemurrageCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyDemurrageERC20.txt"} +{"contractName":"MastercopyInflationaryERC20","deployedAddress":"0x0d52CBB59F817f23861b4571F1c056e7E3FaC6cE","sourcePath":"src/lift/InflationaryCircles.sol:InflationaryCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyInflationaryERC20.txt"} +{"contractName":"MastercopyStandardVault","deployedAddress":"0x7881Eca1d73a2Da217Ac206Ae281048BdA0E1a94","sourcePath":"src/treasury/StandardVault.sol:StandardVault","constructor-args":"","argumentsFile":"constructorArgs_MastercopyStandardVault.txt"} diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-rc-0.3.7-alpha-b824758-241007-120349.log b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-rc-0.3.7-alpha-b824758-241007-120349.log new file mode 100644 index 0000000..abc87a2 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-rc-0.3.7-alpha-b824758-241007-120349.log @@ -0,0 +1,18 @@ +Chiado deployment +================= +Deployment Date: 2024-10-07 12:03:49 +Version: rc-0.3.7-alpha +Git Commit: b824758e79ab581278c0f17bd03bde7855161afc +Deployer Address: 0x7619F26728Ced663E50E578EB6ff42430931564c, Intitial nonce: 193 +Compiler Version: v0.8.23+commit.f704f362 + +Deployed Contracts: +Hub: 0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb +Migration: 0xA8366F19208FaE17f3707f5164bDC3c73eea2219 +NameRegistry: 0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984 +ERC20Lift: 0xC7E57f5356c46b53A2A1395766B90A5d57981eDf +StandardTreasury: 0x86eA22F850F7fe97De700d841200e148347Ca231 +BaseGroupMintPolicy: 0x92bfAbDc2D2608751C617e48469278CF19ef3C77 +MastercopyDemurrageERC20: 0xcB42B236c3e58857A7F3D45df427535976e09027 +MastercopyInflationaryERC20: 0x0d52CBB59F817f23861b4571F1c056e7E3FaC6cE +MastercopyStandardVault: 0x7881Eca1d73a2Da217Ac206Ae281048BdA0E1a94 diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_BaseGroupMintPolicy.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_BaseGroupMintPolicy.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_BaseGroupMintPolicy.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_ERC20Lift.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_ERC20Lift.txt new file mode 100644 index 0000000..b5b124b --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_ERC20Lift.txt @@ -0,0 +1 @@ +0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984 0xcB42B236c3e58857A7F3D45df427535976e09027 0x0d52CBB59F817f23861b4571F1c056e7E3FaC6cE diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Hub.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Hub.txt new file mode 100644 index 0000000..6f01ca3 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Hub.txt @@ -0,0 +1 @@ +0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984 0xA8366F19208FaE17f3707f5164bDC3c73eea2219 0xC7E57f5356c46b53A2A1395766B90A5d57981eDf 0x86eA22F850F7fe97De700d841200e148347Ca231 1675209600 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyDemurrageERC20.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyDemurrageERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyDemurrageERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyInflationaryERC20.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyInflationaryERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyInflationaryERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyStandardVault.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyStandardVault.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyStandardVault.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Migration.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Migration.txt new file mode 100644 index 0000000..9c81f53 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Migration.txt @@ -0,0 +1 @@ +0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 1675209600 diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_NameRegistry.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_NameRegistry.txt new file mode 100644 index 0000000..9157c3f --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_NameRegistry.txt @@ -0,0 +1 @@ +0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_StandardTreasury.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_StandardTreasury.txt new file mode 100644 index 0000000..2f805dc --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_StandardTreasury.txt @@ -0,0 +1 @@ +0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 0x7881Eca1d73a2Da217Ac206Ae281048BdA0E1a94 diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_BaseGroupMintPolicy.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_BaseGroupMintPolicy.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_BaseGroupMintPolicy.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_ERC20Lift.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_ERC20Lift.txt new file mode 100644 index 0000000..f735623 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_ERC20Lift.txt @@ -0,0 +1 @@ +0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 0x6192069E85afBD09D03f7e85eB6c35982A847e16 0xBF2F902d56d7ad2F2B1d674DC8B4d8C58354e7e5 0xD3529a99A7881DF7D11829135759AD0e4A8Ab587 diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Hub.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Hub.txt new file mode 100644 index 0000000..1629336 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Hub.txt @@ -0,0 +1 @@ +0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0x6192069E85afBD09D03f7e85eB6c35982A847e16 0x3483cE5904413bc4Fb83DA2E43540eD769752C88 0x1CAc5fE351EFFa130223aC0f84EB6B7Efc7a66AD 0x421ae522F756412808Ff62F74C20e5ebDA8C4208 1602720000 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyDemurrageERC20.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyDemurrageERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyDemurrageERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyInflationaryERC20.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyInflationaryERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyInflationaryERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyStandardVault.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyStandardVault.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyStandardVault.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Migration.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Migration.txt new file mode 100644 index 0000000..887bd17 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Migration.txt @@ -0,0 +1 @@ +0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 1602720000 diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_NameRegistry.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_NameRegistry.txt new file mode 100644 index 0000000..008cc9b --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_NameRegistry.txt @@ -0,0 +1 @@ +0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_StandardTreasury.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_StandardTreasury.txt new file mode 100644 index 0000000..85ffdf4 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_StandardTreasury.txt @@ -0,0 +1 @@ +0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 0x6604C8eBDD57F3771e4D0Cb3A174AfaEAf38C463 diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-artefacts-rc-0.3.7-alpha-b824758-241007-121112.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-artefacts-rc-0.3.7-alpha-b824758-241007-121112.txt new file mode 100644 index 0000000..ce09ae9 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-artefacts-rc-0.3.7-alpha-b824758-241007-121112.txt @@ -0,0 +1,9 @@ +{"contractName":"Hub","deployedAddress":"0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb","sourcePath":"src/hub/Hub.sol:Hub","constructor-args":"0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0x6192069E85afBD09D03f7e85eB6c35982A847e16 0x3483cE5904413bc4Fb83DA2E43540eD769752C88 0x1CAc5fE351EFFa130223aC0f84EB6B7Efc7a66AD 0x421ae522F756412808Ff62F74C20e5ebDA8C4208 1602720000 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json","argumentsFile":"constructorArgs_Hub.txt"} +{"contractName":"Migration","deployedAddress":"0x3483cE5904413bc4Fb83DA2E43540eD769752C88","sourcePath":"src/migration/Migration.sol:Migration","constructor-args":"0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 1602720000","argumentsFile":"constructorArgs_Migration.txt"} +{"contractName":"NameRegistry","deployedAddress":"0x6192069E85afBD09D03f7e85eB6c35982A847e16","sourcePath":"src/names/NameRegistry.sol:NameRegistry","constructor-args":"0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb","argumentsFile":"constructorArgs_NameRegistry.txt"} +{"contractName":"ERC20Lift","deployedAddress":"0x1CAc5fE351EFFa130223aC0f84EB6B7Efc7a66AD","sourcePath":"src/lift/ERC20Lift.sol:ERC20Lift","constructor-args":"0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 0x6192069E85afBD09D03f7e85eB6c35982A847e16 0xBF2F902d56d7ad2F2B1d674DC8B4d8C58354e7e5 0xD3529a99A7881DF7D11829135759AD0e4A8Ab587","argumentsFile":"constructorArgs_ERC20Lift.txt"} +{"contractName":"StandardTreasury","deployedAddress":"0x421ae522F756412808Ff62F74C20e5ebDA8C4208","sourcePath":"src/treasury/StandardTreasury.sol:StandardTreasury","constructor-args":"0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 0x6604C8eBDD57F3771e4D0Cb3A174AfaEAf38C463","argumentsFile":"constructorArgs_StandardTreasury.txt"} +{"contractName":"BaseGroupMintPolicy","deployedAddress":"0x48F6B0aa3Ca905C9DbE41717c7664639107257da","sourcePath":"src/groups/BaseMintPolicy.sol:MintPolicy","constructor-args":"","argumentsFile":"constructorArgs_BaseGroupMintPolicy.txt"} +{"contractName":"MastercopyDemurrageERC20","deployedAddress":"0xBF2F902d56d7ad2F2B1d674DC8B4d8C58354e7e5","sourcePath":"src/lift/DemurrageCircles.sol:DemurrageCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyDemurrageERC20.txt"} +{"contractName":"MastercopyInflationaryERC20","deployedAddress":"0xD3529a99A7881DF7D11829135759AD0e4A8Ab587","sourcePath":"src/lift/InflationaryCircles.sol:InflationaryCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyInflationaryERC20.txt"} +{"contractName":"MastercopyStandardVault","deployedAddress":"0x6604C8eBDD57F3771e4D0Cb3A174AfaEAf38C463","sourcePath":"src/treasury/StandardVault.sol:StandardVault","constructor-args":"","argumentsFile":"constructorArgs_MastercopyStandardVault.txt"} diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-rc-0.3.7-alpha-b824758-241007-121112.log b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-rc-0.3.7-alpha-b824758-241007-121112.log new file mode 100644 index 0000000..c1e6729 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-rc-0.3.7-alpha-b824758-241007-121112.log @@ -0,0 +1,18 @@ +Gnosis Chain deployment +================= +Deployment Date: 2024-10-07 12:11:12 +Version: rc-0.3.7-alpha +Git Commit: b824758e79ab581278c0f17bd03bde7855161afc +Deployer Address: 0x7619F26728Ced663E50E578EB6ff42430931564c, Initial nonce: 86 +Compiler Version: v0.8.23+commit.f704f362 + +Deployed Contracts: +Hub: 0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb +Migration: 0x3483cE5904413bc4Fb83DA2E43540eD769752C88 +NameRegistry: 0x6192069E85afBD09D03f7e85eB6c35982A847e16 +ERC20Lift: 0x1CAc5fE351EFFa130223aC0f84EB6B7Efc7a66AD +StandardTreasury: 0x421ae522F756412808Ff62F74C20e5ebDA8C4208 +BaseGroupMintPolicy: 0x48F6B0aa3Ca905C9DbE41717c7664639107257da +MastercopyDemurrageERC20: 0xBF2F902d56d7ad2F2B1d674DC8B4d8C58354e7e5 +MastercopyInflationaryERC20: 0xD3529a99A7881DF7D11829135759AD0e4A8Ab587 +MastercopyStandardVault: 0x6604C8eBDD57F3771e4D0Cb3A174AfaEAf38C463