From 3633a7f429c0ba532f32c1a70a17f41884dddd4c Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 1 Aug 2024 16:16:30 +0200 Subject: [PATCH 01/25] (review): response strategy --- reviews/202407-gnosis/01-report.md | 5 +++++ reviews/202407-gnosis/02-reply.md | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 reviews/202407-gnosis/01-report.md create mode 100644 reviews/202407-gnosis/02-reply.md diff --git a/reviews/202407-gnosis/01-report.md b/reviews/202407-gnosis/01-report.md new file mode 100644 index 0000000..3a8ab9d --- /dev/null +++ b/reviews/202407-gnosis/01-report.md @@ -0,0 +1,5 @@ +# External review of v0.3.4-alpha + +Report done by internal Gnosis review team. + +https://gnosischain.notion.site/CirclesV2-Audit-2f846eba6e2c4540a256f518506428ad diff --git a/reviews/202407-gnosis/02-reply.md b/reviews/202407-gnosis/02-reply.md new file mode 100644 index 0000000..175eb4a --- /dev/null +++ b/reviews/202407-gnosis/02-reply.md @@ -0,0 +1,16 @@ +# Addressing review comments + +## Attacker can steal tokens from user who opted out consented flow + +### Summary + +If any user opts out of consented flow by calling `setAdvancedUsageFlag()` with argument `ADVANCED_FLAG_OPTOUT_CONSENTEDFLOW` they accept that parties they do not trust may hold their tokens due to their tokens being used as a transition in a flow matrix. Due to the way group tokens are minted when operating a flow matrix, any group can steal every tokens held by a user. Without consented flow, an attacker can deploy a group and steal tokens from the user without requiring the trust of the user. + +(for full description, see report) + +### Response strategy: +1. consider only consented flow, ie. remove ability to opt-out. Even if 3. is adopted as the elegant fix for netting the flow matrix correctly over group mints, it still leaves open the first premise of the severe attack: "Attacker can steal tokens from user who opted out consented flow", which matters once different Circles identifiers have market price valuations. +2. consider requiring the flow operator must be authorised for all touched vertices: + - (re)imposing this restriction makes it a lot harder to iterate on improvements for flow operators; + - on the other hand, enabling it would be a strong mechanism against yet unknown exploits in the protocol. This however needs to be balanced with our confidence in the correctness of the implementation. +3. consider improving how the flow matrix should be netted over group mints along a flow path to remove the error of nullable path edges. \ No newline at end of file From 0558571bf287f472cb0a806559e057e70b061d2e Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 1 Aug 2024 19:43:39 +0200 Subject: [PATCH 02/25] (hub): introduce receiver for internal _groupMint, and update public groupMint() function --- src/hub/Hub.sol | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 00bcd45..1736f2f 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -401,7 +401,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * @param _group address of the group avatar to mint Circles of * @param _collateralAvatars array of (personal or group) avatar addresses to be used as collateral * @param _amounts array of amounts of collateral to be used for minting - * @param _data (optional) additional data to be passed to the mint policy, treasury and minter + * @param _data (optional) additional data to be passed to the mint policy, treasury and minter (caller) */ function groupMint( address _group, @@ -413,7 +413,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { for (uint256 i = 0; i < _collateralAvatars.length; i++) { collateral[i] = toTokenId(_collateralAvatars[i]); } - _groupMint(msg.sender, _group, collateral, _amounts, _data); + _groupMint(msg.sender, msg.sender, _group, collateral, _amounts, _data); } /** @@ -606,15 +606,22 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { return uint256(trustMarkers[_truster][_trustee].expiry) >= block.timestamp; } + /** + * @notice Returns true if the receiver trusts the Circles being sent, and if the circles avatar of the Circles + * being sent trusts the receiver (unless this avatar has opted out of consented flow). + * @param _to the address to which the Circles are being sent, must trust the Circles being sent + * @param _circlesAvatar the address of the Circles being sent. For consented flow, this Circles avatar + * must also trust the receiver for tokens to be permitted to flow there under a flow operation. + */ function isPermittedFlow(address _to, address _circlesAvatar) public view returns (bool) { - // if receiver does not trust the Circles being sent, then the flow is not consented regardless + // if receiver does not trust the Circles being sent, then the flow is not permitted regardless if (uint256(trustMarkers[_to][_circlesAvatar].expiry) < block.timestamp) return false; // if the advanced usage flag is set to opt-out of consented flow, // then the uni-directional trust is sufficient if (advancedUsageFlags[_circlesAvatar] & ADVANCED_FLAG_OPTOUT_CONSENTEDFLOW != bytes32(0)) { return true; } - // however, by default the consented flow requires bi-directional trust from center to receiver + // however, by default the consented flow requires bi-directional trust also from center to receiver return uint256(trustMarkers[_circlesAvatar][_to].expiry) >= block.timestamp; } @@ -622,7 +629,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { /** * @notice Group mint allows to mint group Circles by providing the required collateral. - * @param _sender address of the sender of the group mint, and receiver of minted group Circles + * @param _sender address of the sender of the group mint + * @param _receiver address of the receiver of minted group Circles * @param _group address of the group avatar to mint Circles of * @param _collateral array of (personal or group) avatar addresses to be used as collateral * @param _amounts array of amounts of collateral to be used for minting @@ -630,6 +638,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { */ function _groupMint( address _sender, + address _receiver, address _group, uint256[] memory _collateral, uint256[] memory _amounts, @@ -655,9 +664,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { for (uint256 i = 0; i < _amounts.length; i++) { // _groupMint is only called from the public groupMint function, // or from operateFlowMatrix, and both ensure the collateral ids are derived - // from an address, so we can cast here without checks. + // from a registered address, so we can cast here without checking valid registration if (!isPermittedFlow(_group, _validateAddressFromId(_collateral[i], 2))) { - // Group does not trust collateral. + // Group does not trust collateral, or flow edge is not permitted revert CirclesHubFlowEdgeIsNotPermitted(_group, _collateral[i], 0); } @@ -683,8 +692,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // note: treasury.on1155Received must implement and unpack the GroupMintMetadata to know the group safeBatchTransferFrom(_sender, treasuries[_group], _collateral, _amounts, dataWithGroup); - // mint group Circles to the sender and send the original _data onwards - _mintAndUpdateTotalSupply(_sender, toTokenId(_group), sumAmounts, _data); + // mint group Circles to the receiver and send the original _data onwards + _mintAndUpdateTotalSupply(_receiver, toTokenId(_group), sumAmounts, _data); } function _verifyFlowMatrix( From f31c7034e2349df438df63140e663645ae5a9681 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Fri, 2 Aug 2024 17:31:15 +0200 Subject: [PATCH 03/25] (hub): remove exception on netting the flow for path-based group mints --- src/hub/Hub.sol | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 1736f2f..8aa1251 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -696,6 +696,16 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { _mintAndUpdateTotalSupply(_receiver, toTokenId(_group), sumAmounts, _data); } + /** + * @dev Verify the correctness of the flow matrix describing the path transfer + * @param _flowVertices an ordered list of avatar addresses as the vertices which the path touches + * @param _flow array of flow edges, each edge is a struct with the amount (uint192) + * and streamSinkId (reference to a stream, where for non-terminal flow edges this is 0, and for terminal flow edges + * this must reference the index of the stream in the streams array, starting from 1) + * @param _coordinates unpacked array of coordinates of the flow edges, with 3 coordinates per flow edge: + * Circles identifier being transfered, sender, receiver, each a uint16 referencing the flow vertex. + * @param _closedPath boolean indicating whether the path is a closed path or not + */ function _verifyFlowMatrix( address[] calldata _flowVertices, FlowEdge[] calldata _flow, @@ -762,12 +772,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } // nett the flow, dividing out the different Circle identifiers - // expect for all edges to a group, as they are interpreted - // as a request for group mint in _effectPathTransfers - if (!isGroup(to)) { - nettedFlow[_coordinates[index + 1]] -= flow; - nettedFlow[_coordinates[index + 2]] += flow; - } + nettedFlow[_coordinates[index + 1]] -= flow; + nettedFlow[_coordinates[index + 2]] += flow; + index = index + 3; } } @@ -829,13 +836,14 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { amounts ); } else { - // do group mint, and the sender receives the minted group Circles + // do group mint, and the group itself receives the minted group Circles _groupMint( _flowVertices[_coordinates[index + 1]], // sender, from coordinate - to, // group + to, // receiver, to coordinate + to, // group; for triggering group mint, to == the group to mint for ids, // collateral amounts, // amounts - "" + "" // path-based group mints never send data to the mint policy ); } From 2da189330d8e37ad7ca5177d96f892ca272c32fc Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Sun, 4 Aug 2024 13:55:07 +0200 Subject: [PATCH 04/25] (hub): developer comments on internal function effectPathTransfers, callAcceptanceChecks --- src/hub/Hub.sol | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 8aa1251..20f72ec 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -782,6 +782,14 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { return nettedFlow; } + /** + * @dev Effect the flow edges of the path transfer, this will revert if any balance is insufficient + * @param _flowVertices an ordered list of avatar addresses as the vertices which the path touches + * @param _flow array of flow edges, each edge is a struct with the amount and streamSinkId + * @param _streams array of streams, each stream is a struct that references the source vertex coordinate, + * the ids of the terminal flow edges of this stream, and the data that is passed to the ERC1155 acceptance check + * @param _coordinates unpacked array of coordinates of the flow edges + */ function _effectPathTransfers( address[] calldata _flowVertices, FlowEdge[] calldata _flow, @@ -864,6 +872,13 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } } + /** + * @dev Call the acceptance checks for the streams, and return the netted streams + * @param _flowVertices sorted array of avatar addresses as the vertices which the path touches + * @param _flow array of flow edges + * @param _streams array of streams + * @param _coordinates unpacked array of coordinates of the flow edges + */ function _callAcceptanceChecks( address[] calldata _flowVertices, FlowEdge[] calldata _flow, From 539b9aa001934bc2b6edc07072fca50ad750b6a7 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 5 Aug 2024 19:07:09 +0200 Subject: [PATCH 05/25] (hub): remove optout from consented flow to protect users --- src/hub/Hub.sol | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 00bcd45..d0725d7 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -39,8 +39,6 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { */ address private constant SENTINEL = address(0x1); - bytes32 private constant ADVANCED_FLAG_OPTOUT_CONSENTEDFLOW = bytes32(uint256(1)); - // State variables // /** @@ -107,12 +105,6 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { */ mapping(address => address) public treasuries; - /** - * @notice By default the advanced usage flags should remain set to zero. - * Only for advanced purposes people can consider enabling flags. - */ - mapping(address => bytes32) public advancedUsageFlags; - /** * @notice The iterable mapping of directional trust relations between avatars and * their expiry times. @@ -561,14 +553,6 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { _matchNettedFlows(streamsNettedFlow, matrixNettedFlow); } - function setAdvancedUsageFlag(bytes32 _flag) external { - if (avatars[msg.sender] == address(0)) { - // Only registered avatars can set advanced usage flags. - revert CirclesAvatarMustBeRegistered(msg.sender, 3); - } - advancedUsageFlags[msg.sender] = _flag; - } - // Public functions /** @@ -606,15 +590,18 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { return uint256(trustMarkers[_truster][_trustee].expiry) >= block.timestamp; } + /** + * @notice Returns true if the flow to the receiver is permitted. + * The receiver must trust the Circles being sent, and the Circles avatar associated with + * the Circles must trust the receiver. + * @param _to Address of the receiver + * @param _circlesAvatar Address of the Circles avatar of the Circles being sent + * @return permitted true if the flow is permitted, false otherwise + */ function isPermittedFlow(address _to, address _circlesAvatar) public view returns (bool) { // if receiver does not trust the Circles being sent, then the flow is not consented regardless if (uint256(trustMarkers[_to][_circlesAvatar].expiry) < block.timestamp) return false; - // if the advanced usage flag is set to opt-out of consented flow, - // then the uni-directional trust is sufficient - if (advancedUsageFlags[_circlesAvatar] & ADVANCED_FLAG_OPTOUT_CONSENTEDFLOW != bytes32(0)) { - return true; - } - // however, by default the consented flow requires bi-directional trust from center to receiver + // however, consented flow also requires bi-directional trust from center to receiver return uint256(trustMarkers[_circlesAvatar][_to].expiry) >= block.timestamp; } From 5ddd6255c552ed503336ca37dda20a38080027be Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 6 Aug 2024 23:26:42 +0200 Subject: [PATCH 06/25] (hub): add events for deeper parsing of path transfers --- src/hub/Hub.sol | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 00bcd45..d6cafed 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -132,6 +132,16 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { event Stopped(address indexed avatar); + event FlowEdgeEffected(uint16 flowEdgeId, uint16 streamSinkId); + event StreamCompleted( + address indexed operator, + address indexed from, + address indexed to, + uint256[] ids, + uint256[] amounts, + uint16 streamSinkId + ); + // Modifiers /** @@ -830,6 +840,10 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { ); } + // emit the flow edge's index and the associated stream sink id + // so that terminal flow edges can be matched with streams + emit FlowEdgeEffected(index / 3, _flow[i].streamSinkId); + index = index + 3; } @@ -881,6 +895,10 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { nettedFlow[_streams[i].sourceCoordinate] -= int256(streamTotal); // to recover the receiver coordinate, get the first sink nettedFlow[receiverCoordinate] += int256(streamTotal); + + // emit the stream completed event which expresses the effective "ERC1155:BatchTransfer" event + // for the stream as part of a batch of path transfers. + emit StreamCompleted(msg.sender, _flowVertices[_streams[i].sourceCoordinate], receiver, ids, amounts, i + 1); } return nettedFlow; From e2a0bffcd5e43cc80a224d61695764a1609f029d Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 6 Aug 2024 23:43:49 +0200 Subject: [PATCH 07/25] (DiscountedBalances): mirror event DiscountCost, with a burn (Single)Transfer so that accounting transfers ERC20/ERC1155 tracks the balance without explicit knowledge of DiscountCost event --- src/circles/DiscountedBalances.sol | 2 ++ src/circles/ERC1155.sol | 1 + src/lift/ERC20DiscountedBalances.sol | 3 +++ 3 files changed, 6 insertions(+) diff --git a/src/circles/DiscountedBalances.sol b/src/circles/DiscountedBalances.sol index 47a6636..069c32f 100644 --- a/src/circles/DiscountedBalances.sol +++ b/src/circles/DiscountedBalances.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.24; +import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "../lib/Math64x64.sol"; import "./Demurrage.sol"; @@ -123,6 +124,7 @@ contract DiscountedBalances is Demurrage { uint256 discountCost = discountedBalance.balance - discountedBalanceOnDay; if (discountCost > 0) { emit DiscountCost(_account, _id, discountCost); + emit IERC1155.TransferSingle(msg.sender, _account, address(0), _id, discountCost); } } uint256 updatedBalance = discountedBalanceOnDay + _value; diff --git a/src/circles/ERC1155.sol b/src/circles/ERC1155.sol index 2c4a8af..445f5f0 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 DiscountCost(from, id, discountCost); + emit TransferSingle(operator, from, address(0), id, discountCost); } unchecked { // Overflow not possible: value <= fromBalance diff --git a/src/lift/ERC20DiscountedBalances.sol b/src/lift/ERC20DiscountedBalances.sol index 35c1011..d900b99 100644 --- a/src/lift/ERC20DiscountedBalances.sol +++ b/src/lift/ERC20DiscountedBalances.sol @@ -129,6 +129,7 @@ contract ERC20DiscountedBalances is ERC20Permit, Demurrage, IERC20 { uint256 discountCost = discountedBalance.balance - discountedBalanceOnDay; if (discountCost > 0) { emit DiscountCost(_account, toTokenId(avatar), discountCost); + emit Transfer(_account, address(0), discountCost); } } uint256 updatedBalance = discountedBalanceOnDay + _value; @@ -148,6 +149,7 @@ contract ERC20DiscountedBalances is ERC20Permit, Demurrage, IERC20 { } if (discountCost > 0) { emit DiscountCost(_from, toTokenId(avatar), discountCost); + emit Transfer(_from, address(0), discountCost); } unchecked { _updateBalance(_from, fromBalance - _amount, day); @@ -170,6 +172,7 @@ contract ERC20DiscountedBalances is ERC20Permit, Demurrage, IERC20 { } if (discountCost > 0) { emit DiscountCost(_owner, toTokenId(avatar), discountCost); + emit Transfer(_owner, address(0), discountCost); } unchecked { _updateBalance(_owner, ownerBalance - _amount, day); From b6bb758b0944b6b5bb0dcefd474a8690be6278d1 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 16:19:48 +0200 Subject: [PATCH 08/25] (DiscountedBalances): remove event DiscountCost to save compiled space --- src/circles/Demurrage.sol | 4 ---- src/circles/DiscountedBalances.sol | 1 - src/circles/ERC1155.sol | 1 - src/lift/ERC20DiscountedBalances.sol | 3 --- test/lift/ERC20Demurrage.sol | 2 -- 5 files changed, 11 deletions(-) diff --git a/src/circles/Demurrage.sol b/src/circles/Demurrage.sol index 98fd48a..9d798c1 100644 --- a/src/circles/Demurrage.sol +++ b/src/circles/Demurrage.sol @@ -142,10 +142,6 @@ contract Demurrage is ICirclesDemurrageErrors { */ int128[15] internal R; - // Events - - event DiscountCost(address indexed account, uint256 indexed id, uint256 discountCost); - // Constructor constructor() { diff --git a/src/circles/DiscountedBalances.sol b/src/circles/DiscountedBalances.sol index 069c32f..9e2d07f 100644 --- a/src/circles/DiscountedBalances.sol +++ b/src/circles/DiscountedBalances.sol @@ -123,7 +123,6 @@ contract DiscountedBalances is Demurrage { unchecked { uint256 discountCost = discountedBalance.balance - discountedBalanceOnDay; if (discountCost > 0) { - emit DiscountCost(_account, _id, discountCost); emit IERC1155.TransferSingle(msg.sender, _account, address(0), _id, discountCost); } } diff --git a/src/circles/ERC1155.sol b/src/circles/ERC1155.sol index 445f5f0..8ad5f21 100644 --- a/src/circles/ERC1155.sol +++ b/src/circles/ERC1155.sol @@ -173,7 +173,6 @@ abstract contract ERC1155 is DiscountedBalances, Context, ERC165, IERC1155, IERC revert ERC1155InsufficientBalance(from, fromBalance, value, id); } if (discountCost > 0) { - emit DiscountCost(from, id, discountCost); emit TransferSingle(operator, from, address(0), id, discountCost); } unchecked { diff --git a/src/lift/ERC20DiscountedBalances.sol b/src/lift/ERC20DiscountedBalances.sol index d900b99..07e35f7 100644 --- a/src/lift/ERC20DiscountedBalances.sol +++ b/src/lift/ERC20DiscountedBalances.sol @@ -128,7 +128,6 @@ contract ERC20DiscountedBalances is ERC20Permit, Demurrage, IERC20 { unchecked { uint256 discountCost = discountedBalance.balance - discountedBalanceOnDay; if (discountCost > 0) { - emit DiscountCost(_account, toTokenId(avatar), discountCost); emit Transfer(_account, address(0), discountCost); } } @@ -148,7 +147,6 @@ contract ERC20DiscountedBalances is ERC20Permit, Demurrage, IERC20 { revert ERC20InsufficientBalance(_from, fromBalance, _amount); } if (discountCost > 0) { - emit DiscountCost(_from, toTokenId(avatar), discountCost); emit Transfer(_from, address(0), discountCost); } unchecked { @@ -171,7 +169,6 @@ contract ERC20DiscountedBalances is ERC20Permit, Demurrage, IERC20 { revert ERC20InsufficientBalance(_owner, ownerBalance, _amount); } if (discountCost > 0) { - emit DiscountCost(_owner, toTokenId(avatar), discountCost); emit Transfer(_owner, address(0), discountCost); } unchecked { diff --git a/test/lift/ERC20Demurrage.sol b/test/lift/ERC20Demurrage.sol index 4ec6292..5143f5e 100644 --- a/test/lift/ERC20Demurrage.sol +++ b/test/lift/ERC20Demurrage.sol @@ -87,8 +87,6 @@ contract ERC20LiftTest is Test, TimeCirclesSetup, HumanRegistration { // send 50 CRC from Alice to Bob vm.prank(addresses[0]); - vm.expectEmit(true, true, false, true, address(aliceERC20)); - emit Demurrage.DiscountCost(addresses[0], aliceCirclesId, aliceDiscountCostT2); aliceERC20.transfer(addresses[1], 50 * CRC); (uint256 aliceBalanceT3, uint256 aliceDiscountCostT3) = aliceERC20.balanceOfOnDay(addresses[0], dayT2); From e75a29012c6348a33191927cabd68222d8a74455 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 16:32:36 +0200 Subject: [PATCH 09/25] (hub): remove event FlowEdgeEffected and simplify StreamCompleted event; again for compile size --- src/hub/Hub.sol | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index d6cafed..df904c6 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -132,14 +132,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { event Stopped(address indexed avatar); - event FlowEdgeEffected(uint16 flowEdgeId, uint16 streamSinkId); event StreamCompleted( - address indexed operator, - address indexed from, - address indexed to, - uint256[] ids, - uint256[] amounts, - uint16 streamSinkId + address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); // Modifiers @@ -840,10 +834,6 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { ); } - // emit the flow edge's index and the associated stream sink id - // so that terminal flow edges can be matched with streams - emit FlowEdgeEffected(index / 3, _flow[i].streamSinkId); - index = index + 3; } @@ -898,7 +888,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // emit the stream completed event which expresses the effective "ERC1155:BatchTransfer" event // for the stream as part of a batch of path transfers. - emit StreamCompleted(msg.sender, _flowVertices[_streams[i].sourceCoordinate], receiver, ids, amounts, i + 1); + emit StreamCompleted(msg.sender, _flowVertices[_streams[i].sourceCoordinate], receiver, ids, amounts); } return nettedFlow; From c57a6d6d4b9ef15a5a3a6454bdd7fefc14714177 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 16:57:20 +0200 Subject: [PATCH 10/25] (StandardTreasury): add events for group vault creation, minting group currency and redemption --- src/treasury/StandardTreasury.sol | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/treasury/StandardTreasury.sol b/src/treasury/StandardTreasury.sol index a41ebff..3437ba5 100644 --- a/src/treasury/StandardTreasury.sol +++ b/src/treasury/StandardTreasury.sol @@ -47,6 +47,15 @@ contract StandardTreasury is */ mapping(address => IStandardVault) public vaults; + // 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 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); + // Modifiers /** @@ -145,6 +154,10 @@ contract StandardTreasury is address vault = address(_ensureVault(_group)); // 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); + return this.onERC1155BatchReceived.selector; } @@ -156,6 +169,10 @@ contract StandardTreasury is address vault = address(_ensureVault(_group)); // 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); + return this.onERC1155Received.selector; } @@ -209,6 +226,11 @@ contract StandardTreasury is // burn the collateral Circles from the vault vault.burnCollateral(burnIds, burnValues, _data); + // emit the group redeem event + emit GroupRedeem(group, _id, _value, _data); + emit GroupRedeemCollateralReturn(group, _from, redemptionIds, redemptionValues); + emit GroupRedeemCollateralBurn(group, burnIds, burnValues); + // return the ERC1155 selector for acceptance of the (redeemed) group Circles return this.onERC1155Received.selector; } @@ -259,6 +281,8 @@ contract StandardTreasury is if (address(vault) == address(0)) { vault = _deployVault(); vaults[_group] = vault; + + emit CreateVault(_group, address(vault)); } return vault; } From fa89007e88967b726bb029f6b2c3ed0d624bafee Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 18:44:49 +0200 Subject: [PATCH 11/25] (hub): remove closed paths constraint from operateFlowMatrix --- src/hub/Hub.sol | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 00bcd45..2aa4365 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -546,13 +546,14 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } } - // if no streams are provided, then only closed paths are allowed - bool closedPath = (_streams.length == 0); + // if no streams are provided, the streams will nett to zero for all vertices + // so to pass the acceptance checks, the flow matrix must also nett to zero + // which can be true if for all vertices the sum of incoming and outgoing flow is zero // verify the correctness of the flow matrix describing the path itself, // ie. well-definedness of the flow matrix itself, // check all entities are registered, and the trust relations are respected. - int256[] memory matrixNettedFlow = _verifyFlowMatrix(_flowVertices, _flow, coordinates, closedPath); + int256[] memory matrixNettedFlow = _verifyFlowMatrix(_flowVertices, _flow, coordinates); _effectPathTransfers(_flowVertices, _flow, _streams, coordinates); @@ -690,8 +691,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function _verifyFlowMatrix( address[] calldata _flowVertices, FlowEdge[] calldata _flow, - uint16[] memory _coordinates, - bool _closedPath + uint16[] memory _coordinates ) internal view returns (int256[] memory) { if (3 * _flow.length != _coordinates.length) { // Mismatch in flow and coordinates length. @@ -747,10 +747,6 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // Flow edge is not permitted. revert CirclesHubFlowEdgeIsNotPermitted(to, toTokenId(circlesId), 1); } - if (_closedPath && (to != circlesId || isGroup(circlesId))) { - // Closed paths can only return personal Circles to source. - revert CirclesHubOnClosedPathOnlyPersonalCirclesCanReturnToAvatar(to, toTokenId(circlesId)); - } // nett the flow, dividing out the different Circle identifiers // expect for all edges to a group, as they are interpreted @@ -853,7 +849,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { Stream[] calldata _streams, uint16[] memory _coordinates ) internal returns (int256[] memory) { - // initialize netted flow + // initialize netted flow to zero int256[] memory nettedFlow = new int256[](_flowVertices.length); // effect the stream transfers with acceptance calls From 8547231c76f78277e1456f4031783a76a9a2d2f0 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 19:29:38 +0200 Subject: [PATCH 12/25] (proxy): make mastercopy storage slot internal --- src/proxy/Proxy.sol | 54 ++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 37 deletions(-) diff --git a/src/proxy/Proxy.sol b/src/proxy/Proxy.sol index 27f5fc9..9265bec 100755 --- a/src/proxy/Proxy.sol +++ b/src/proxy/Proxy.sol @@ -1,9 +1,8 @@ // SPDX-License-Identifier: AGPL-3.0-only -// Adapted from https://github.com/gnosis/safe-contracts +// Adapted from https://github.com/gnosis/safe-contracts (originally) +// and updated with https://github.com/safe-global/safe-smart-account/blob/main/contracts/proxies/SafeProxy.sol pragma solidity >=0.8.4; -import "../errors/Errors.sol"; - /// @title IProxy - interface to access master copy of the proxy on-chain interface IProxy { function masterCopy() external view returns (address); @@ -14,49 +13,30 @@ interface IProxy { /// @author Stefan George - /// @author Richard Meissner - contract Proxy { - // masterCopy always needs to be first declared variable, - // to ensure that it is at the same location in the contracts - // to which calls are delegated. - // To reduce deployment costs this variable is internal - // and needs to be retrieved via `getStorageAt` - address public masterCopy; - - /// @dev Constructor function sets address of master copy contract. - /// @param _masterCopy Master copy address. - constructor(address _masterCopy) { - if (_masterCopy == address(0)) { - // Invalid master copy address provided - revert(); - } - masterCopy = _masterCopy; + // Singleton always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated. + // To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt` + address internal singleton; + + /** + * @notice Constructor function sets address of singleton contract. + * @param _singleton Singleton address. + */ + constructor(address _singleton) { + require(_singleton != address(0), "Invalid singleton address provided"); + singleton = _singleton; } - // todo: consider removing payable + /// @dev Fallback function forwards all transactions and returns all received return data. fallback() external payable { - _fallback(); - } - - receive() external payable { - _fallback(); - } - - // -- internal functions - - /// @dev Fallback function forwards all transactions and - /// returns all received return data. - function _fallback() internal { // solhint-disable-next-line no-inline-assembly assembly { - let _singleton := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff) - // 0xa619486e == keccak("masterCopy()"). - // The value is right padded to 32-bytes with 0s - // solhint-disable-next-line max-line-length + let _singleton := sload(0) + // 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0s if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) { - mstore(0, _singleton) + mstore(0, shr(12, shl(12, _singleton))) return(0, 0x20) } calldatacopy(0, 0, calldatasize()) - // solhint-disable-next-line max-line-length let success := delegatecall(gas(), _singleton, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) if eq(success, 0) { revert(0, returndatasize()) } From dbf332b06e1a63b838be88053821219b84169dbf Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 19:52:12 +0200 Subject: [PATCH 13/25] (proxy): make proxy no longer payable, because they should never receive xDAI --- src/proxy/Proxy.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/proxy/Proxy.sol b/src/proxy/Proxy.sol index 9265bec..2b4e61d 100755 --- a/src/proxy/Proxy.sol +++ b/src/proxy/Proxy.sol @@ -27,7 +27,9 @@ contract Proxy { } /// @dev Fallback function forwards all transactions and returns all received return data. - fallback() external payable { + /// The fallback function is not payable because at no plpointace in Circles do these proxy contracts + /// need to receive xDAI (on Gnosis Chain, or Ether if they are deployed on Ethereum) + fallback() external { // solhint-disable-next-line no-inline-assembly assembly { let _singleton := sload(0) From 9386305f64622829c03c7f3b5a766c888c0a8509 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 21:10:43 +0200 Subject: [PATCH 14/25] (Circles): make calculateIssuance external on Hub, so that we can apply the same isHuman check on the view function --- src/circles/Circles.sol | 104 +++++++++++++++++------------------ src/hub/Hub.sol | 18 +++++- test/circles/MockCircles.sol | 4 ++ 3 files changed, 73 insertions(+), 53 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index baf4829..2d8bed7 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -77,57 +77,6 @@ contract Circles is ERC1155, ICirclesErrors { // Public functions - /** - * @notice Calculate the demurraged issuance for a human's avatar. - * @param _human Address of the human's avatar to calculate the issuance for. - * @return issuance The issuance in attoCircles. - * @return startPeriod The start of the claimable period. - * @return endPeriod The end of the claimable period. - */ - function calculateIssuance(address _human) public view returns (uint256, uint256, uint256) { - MintTime storage mintTime = mintTimes[_human]; - if (mintTime.mintV1Status != address(0) && mintTime.mintV1Status != CIRCLES_STOPPED_V1) { - // Circles v1 contract cannot be active. - 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 - return (0, 0, 0); - } - - // calculate the start of the claimable period - uint256 startMint = _max(block.timestamp - MAX_CLAIM_DURATION, mintTime.lastMintTime); - - // day of start of mint, dA - uint256 dA = uint256(day(startMint)); - - // day of current block, dB - uint256 dB = uint256(day(block.timestamp)); - - // the difference of days between dB and dA used for the table lookups - uint256 n = dB - dA; - - // calculate the number of completed hours in day A until `startMint` - int128 k = Math64x64.fromUInt((startMint - (dA * 1 days + inflationDayZero)) / 1 hours); - - // Calculate the number of incompleted hours remaining in day B from current timestamp - int128 l = Math64x64.fromUInt(((dB + 1) * 1 days + inflationDayZero - block.timestamp) / 1 hours + 1); - - // calculate the overcounted (demurraged) k (in day A) and l (in day B) hours - int128 overcount = Math64x64.add(Math64x64.mul(R[n], k), l); - - // subtract the overcount from the total issuance, and convert to attoCircles - return ( - Math64x64.mulu(Math64x64.sub(T[n], overcount), EXA), - // start of the claimable period - inflationDayZero + dA * 1 days + Math64x64.mulu(k, 1 hours), - // end of the claimable period - inflationDayZero + dB * 1 days + 1 days - Math64x64.mulu(l, 1 hours) - ); - } - /** * Inflationary balance of an account for a Circles identifier. Careful, * calculating the inflationary balance can introduce numerical errors @@ -189,12 +138,63 @@ contract Circles is ERC1155, ICirclesErrors { // Internal functions + /** + * @notice Calculate the demurraged issuance for a human's avatar. + * @param _human Address of the human's avatar to calculate the issuance for. + * @return issuance The issuance in attoCircles. + * @return startPeriod The start of the claimable period. + * @return endPeriod The end of the claimable period. + */ + function _calculateIssuance(address _human) internal view returns (uint256, uint256, uint256) { + MintTime storage mintTime = mintTimes[_human]; + if (mintTime.mintV1Status != address(0) && mintTime.mintV1Status != CIRCLES_STOPPED_V1) { + // Circles v1 contract cannot be active. + 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 + return (0, 0, 0); + } + + // calculate the start of the claimable period + uint256 startMint = _max(block.timestamp - MAX_CLAIM_DURATION, mintTime.lastMintTime); + + // day of start of mint, dA + uint256 dA = uint256(day(startMint)); + + // day of current block, dB + uint256 dB = uint256(day(block.timestamp)); + + // the difference of days between dB and dA used for the table lookups + uint256 n = dB - dA; + + // calculate the number of completed hours in day A until `startMint` + int128 k = Math64x64.fromUInt((startMint - (dA * 1 days + inflationDayZero)) / 1 hours); + + // Calculate the number of incompleted hours remaining in day B from current timestamp + int128 l = Math64x64.fromUInt(((dB + 1) * 1 days + inflationDayZero - block.timestamp) / 1 hours + 1); + + // calculate the overcounted (demurraged) k (in day A) and l (in day B) hours + int128 overcount = Math64x64.add(Math64x64.mul(R[n], k), l); + + // subtract the overcount from the total issuance, and convert to attoCircles + return ( + Math64x64.mulu(Math64x64.sub(T[n], overcount), EXA), + // start of the claimable period + inflationDayZero + dA * 1 days + Math64x64.mulu(k, 1 hours), + // end of the claimable period + inflationDayZero + dB * 1 days + 1 days - Math64x64.mulu(l, 1 hours) + ); + } + /** * @notice Claim issuance for a human's avatar and update the last mint time. * @param _human Address of the human's avatar to claim the issuance for. */ function _claimIssuance(address _human) internal { - (uint256 issuance, uint256 startPeriod, uint256 endPeriod) = calculateIssuance(_human); + (uint256 issuance, uint256 startPeriod, uint256 endPeriod) = _calculateIssuance(_human); if (issuance == 0) { // No issuance to claim, simply return without reverting return; diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 00bcd45..83fb9b7 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -381,6 +381,22 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { _claimIssuance(msg.sender); } + /** + * @notice Calculate the demurraged issuance for a human's avatar. + * @param _human Address of the human's avatar to calculate the issuance for. + * @return issuance The issuance in attoCircles. + * @return startPeriod The start of the claimable period. + * @return endPeriod The end of the claimable period. + */ + function calculateIssuance(address _human) external view returns (uint256, uint256, uint256) { + if (!isHuman(_human)) { + // Only avatars registered as human can calculate issuance. + // If the avatar is not registered as human, return 0 issuance. + return (0, 0, 0); + } + return _calculateIssuance(_human); + } + /** * @notice Calculate issuance allows to calculate the issuance for a human avatar with a check * to update the v1 mint status if updated. @@ -393,7 +409,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // check if v1 Circles is known to be stopped and update status _checkHumanV1CirclesStatus(_human); // calculate issuance for the human avatar, but don't mint - return calculateIssuance(_human); + return _calculateIssuance(_human); } /** diff --git a/test/circles/MockCircles.sol b/test/circles/MockCircles.sol index 8697f34..ce54199 100644 --- a/test/circles/MockCircles.sol +++ b/test/circles/MockCircles.sol @@ -25,4 +25,8 @@ contract MockCircles is Circles { require(mintTimes[msg.sender].lastMintTime != 0, "Circles: Not registered"); _claimIssuance(msg.sender); } + + function calculateIssuance(address _human) external view returns (uint256, uint256, uint256) { + return _calculateIssuance(_human); + } } From df2d292169f4e974d258b360a8ec016972595b97 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 22:09:44 +0200 Subject: [PATCH 15/25] (Circles, (ERC20)DiscountedBalances, Hub): optimise storage read/writes for memory where applicable --- src/circles/Circles.sol | 8 +++++--- src/circles/DiscountedBalances.sol | 6 ++++-- src/hub/Hub.sol | 17 ++++++++++------- src/lift/ERC20DiscountedBalances.sol | 6 ++++-- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index baf4829..2486f2b 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -85,7 +85,7 @@ contract Circles is ERC1155, ICirclesErrors { * @return endPeriod The end of the claimable period. */ function calculateIssuance(address _human) public view returns (uint256, uint256, uint256) { - MintTime storage mintTime = mintTimes[_human]; + 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); @@ -211,7 +211,7 @@ contract Circles is ERC1155, ICirclesErrors { _mint(_account, _id, _value, _data); uint64 today = day(block.timestamp); - DiscountedBalance storage totalSupplyBalance = discountedTotalSupplies[_id]; + DiscountedBalance memory totalSupplyBalance = discountedTotalSupplies[_id]; uint256 newTotalSupply = _calculateDiscountedBalance(totalSupplyBalance.balance, today - totalSupplyBalance.lastUpdatedDay) + _value; if (newTotalSupply > MAX_VALUE) { @@ -220,6 +220,7 @@ contract Circles is ERC1155, ICirclesErrors { } totalSupplyBalance.balance = uint192(newTotalSupply); totalSupplyBalance.lastUpdatedDay = today; + discountedTotalSupplies[_id] = totalSupplyBalance; } function _burnAndUpdateTotalSupply(address _account, uint256 _id, uint256 _value) internal { @@ -227,7 +228,7 @@ contract Circles is ERC1155, ICirclesErrors { _burn(_account, _id, _value); uint64 today = day(block.timestamp); - DiscountedBalance storage totalSupplyBalance = discountedTotalSupplies[_id]; + DiscountedBalance memory totalSupplyBalance = discountedTotalSupplies[_id]; uint256 discountedTotalSupply = _calculateDiscountedBalance(totalSupplyBalance.balance, today - totalSupplyBalance.lastUpdatedDay); if (discountedTotalSupply < _value) { @@ -242,6 +243,7 @@ contract Circles is ERC1155, ICirclesErrors { totalSupplyBalance.balance = uint192(discountedTotalSupply - _value); } totalSupplyBalance.lastUpdatedDay = today; + discountedTotalSupplies[_id] = totalSupplyBalance; } // Private functions diff --git a/src/circles/DiscountedBalances.sol b/src/circles/DiscountedBalances.sol index 47a6636..7d91264 100644 --- a/src/circles/DiscountedBalances.sol +++ b/src/circles/DiscountedBalances.sol @@ -95,9 +95,10 @@ contract DiscountedBalances is Demurrage { // DiscountedBalances: balance exceeds maximum value revert CirclesDemurrageAmountExceedsMaxUint190(_account, _id, _balance, 0); } - DiscountedBalance storage discountedBalance = discountedBalances[_id][_account]; + DiscountedBalance memory discountedBalance = discountedBalances[_id][_account]; discountedBalance.balance = uint192(_balance); discountedBalance.lastUpdatedDay = _day; + discountedBalances[_id][_account] = discountedBalance; } /** @@ -108,7 +109,7 @@ contract DiscountedBalances is Demurrage { * @param _day Day since inflation_day_zero to discount the balance to */ function _discountAndAddToBalance(address _account, uint256 _id, uint256 _value, uint64 _day) internal { - DiscountedBalance storage discountedBalance = discountedBalances[_id][_account]; + 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); @@ -132,5 +133,6 @@ contract DiscountedBalances is Demurrage { } discountedBalance.balance = uint192(updatedBalance); discountedBalance.lastUpdatedDay = _day; + discountedBalances[_id][_account] = discountedBalance; } } diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 00bcd45..148731e 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -425,14 +425,15 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // Only human can call stop. revert CirclesHubMustBeHuman(msg.sender, 2); } - MintTime storage mintTime = mintTimes[msg.sender]; + uint96 lastMintTime = mintTimes[msg.sender].lastMintTime; // check if already stopped - if (mintTime.lastMintTime == INDEFINITE_FUTURE) { + if (lastMintTime == INDEFINITE_FUTURE) { return; } // stop future mints of personal Circles // by setting the last mint time to indefinite future. - mintTime.lastMintTime = INDEFINITE_FUTURE; + lastMintTime = INDEFINITE_FUTURE; + mintTimes[msg.sender].lastMintTime = lastMintTime; emit Stopped(msg.sender); } @@ -446,8 +447,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // Only personal Circles can have a status of boolean stopped. revert CirclesHubMustBeHuman(_human, 3); } - MintTime storage mintTime = mintTimes[msg.sender]; - return (mintTime.lastMintTime == INDEFINITE_FUTURE); + uint96 lastMintTime = mintTimes[msg.sender].lastMintTime; + return (lastMintTime == INDEFINITE_FUTURE); } /** @@ -912,9 +913,10 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // set the last mint time to the current timestamp for invited human // and register the v1 Circles contract status v1CirclesStatus = _avatarV1CirclesStatus(_human); - MintTime storage mintTime = mintTimes[_human]; + MintTime memory mintTime = mintTimes[_human]; mintTime.mintV1Status = v1CirclesStatus; mintTime.lastMintTime = uint96(block.timestamp); + mintTimes[_human] = mintTime; // trust self indefinitely, cannot be altered later _trust(_human, _human, INDEFINITE_FUTURE); @@ -1032,7 +1034,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * @param _mintV1Status Mint status of the v1 Circles contract. */ function _updateMintV1Status(address _human, address _mintV1Status) internal { - MintTime storage mintTime = mintTimes[_human]; + MintTime memory mintTime = mintTimes[_human]; // precautionary check to ensure that the last mint time is already set // as this marks whether an avatar is registered as human or not if (mintTime.lastMintTime == 0) { @@ -1044,6 +1046,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { if (mintTime.mintV1Status != _mintV1Status) { mintTime.mintV1Status = _mintV1Status; mintTime.lastMintTime = uint96(block.timestamp); + mintTimes[_human] = mintTime; } } diff --git a/src/lift/ERC20DiscountedBalances.sol b/src/lift/ERC20DiscountedBalances.sol index 35c1011..1e15a41 100644 --- a/src/lift/ERC20DiscountedBalances.sol +++ b/src/lift/ERC20DiscountedBalances.sol @@ -107,13 +107,14 @@ contract ERC20DiscountedBalances is ERC20Permit, Demurrage, IERC20 { // Balance exceeds maximum value. revert CirclesDemurrageAmountExceedsMaxUint190(_account, toTokenId(avatar), _balance, 0); } - DiscountedBalance storage discountedBalance = discountedBalances[_account]; + DiscountedBalance memory discountedBalance = discountedBalances[_account]; discountedBalance.balance = uint192(_balance); discountedBalance.lastUpdatedDay = _day; + discountedBalances[_account] = discountedBalance; } function _discountAndAddToBalance(address _account, uint256 _value, uint64 _day) internal { - DiscountedBalance storage discountedBalance = discountedBalances[_account]; + DiscountedBalance memory discountedBalance = discountedBalances[_account]; if (_day < discountedBalance.lastUpdatedDay) { // ERC20 DiscountedBalances: day is before last updated day revert CirclesDemurrageDayBeforeLastUpdatedDay( @@ -138,6 +139,7 @@ contract ERC20DiscountedBalances is ERC20Permit, Demurrage, IERC20 { } discountedBalance.balance = uint192(updatedBalance); discountedBalance.lastUpdatedDay = _day; + discountedBalances[_account] = discountedBalance; } function _transfer(address _from, address _to, uint256 _amount) internal { From 2f80080cf8bfe8e7e49748462a53972c29cc74ff Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 22:21:17 +0200 Subject: [PATCH 16/25] (Demurrage): improve storage reads and writes for caching the demurrage factor table --- src/circles/Demurrage.sol | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/circles/Demurrage.sol b/src/circles/Demurrage.sol index 98fd48a..1581408 100644 --- a/src/circles/Demurrage.sol +++ b/src/circles/Demurrage.sol @@ -242,22 +242,27 @@ contract Demurrage is ICirclesDemurrageErrors { } function _calculateDemurrageFactor(uint256 _dayDifference) internal view returns (int128) { - if (_dayDifference <= R_TABLE_LOOKUP && R[_dayDifference] != 0) { - return R[_dayDifference]; - } else { - return Math64x64.pow(GAMMA_64x64, _dayDifference); + if (_dayDifference <= R_TABLE_LOOKUP) { + // if the day difference is in the lookup table, return the value from the table + int128 demurrageFactor = R[_dayDifference]; + if (demurrageFactor != 0) { + return demurrageFactor; + } } + // if the day difference is not in the lookup table, calculate the value + return Math64x64.pow(GAMMA_64x64, _dayDifference); } function _calculateDemurrageFactorAndCache(uint256 _dayDifference) internal returns (int128) { if (_dayDifference <= R_TABLE_LOOKUP) { - if (R[_dayDifference] == 0) { + int128 demurrageFactor = R[_dayDifference]; + if (demurrageFactor == 0) { // for proxy ERC20 contracts, the storage does not contain the R table yet // so compute it lazily and store it in the table - int128 r = Math64x64.pow(GAMMA_64x64, _dayDifference); - R[_dayDifference] = r; + demurrageFactor = Math64x64.pow(GAMMA_64x64, _dayDifference); + R[_dayDifference] = demurrageFactor; } - return R[_dayDifference]; + return demurrageFactor; } else { return Math64x64.pow(GAMMA_64x64, _dayDifference); } From e0fdf18d3d56fbdf10cf5a13385d91881b6f334d Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 22:36:44 +0200 Subject: [PATCH 17/25] (errors): remove now redundant error relating to closed paths constraint --- src/errors/Errors.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 9894daf..ffd15b3 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -24,8 +24,6 @@ interface IHubErrors { error CirclesHubFlowEdgeIsNotPermitted(address receiver, uint256 circlesId, uint8 code); - error CirclesHubOnClosedPathOnlyPersonalCirclesCanReturnToAvatar(address failedReceiver, uint256 circlesId); - error CirclesHubFlowVerticesMustBeSorted(); error CirclesHubFlowEdgeStreamMismatch(uint16 flowEdgeId, uint16 streamId, uint8 code); From 72b61011447841c206b76a683a87ea8bbfe8f69a Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 22:49:12 +0200 Subject: [PATCH 18/25] forge install: abdk-libraries-solidity --- .gitmodules | 5 ++++- lib/abdk-libraries-solidity | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) create mode 160000 lib/abdk-libraries-solidity diff --git a/.gitmodules b/.gitmodules index 257ba39..9eccac5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,4 +4,7 @@ [submodule "lib/openzeppelin-contracts"] path = lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts - branch = v5.0.2 \ No newline at end of file + branch = v5.0.2 +[submodule "lib/abdk-libraries-solidity"] + path = lib/abdk-libraries-solidity + url = https://github.com/abdk-consulting/abdk-libraries-solidity diff --git a/lib/abdk-libraries-solidity b/lib/abdk-libraries-solidity new file mode 160000 index 0000000..5e1e7c1 --- /dev/null +++ b/lib/abdk-libraries-solidity @@ -0,0 +1 @@ +Subproject commit 5e1e7c11b35f8313d3f7ce11c1b86320d7c0b554 From 813fd6cfc26cf68c950cbf0fd71f15c22acfba4e Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 23:25:29 +0200 Subject: [PATCH 19/25] (lib/Math64x64): replace copied lib from 2021 with proper dependency on latest v3.2 from 2023 --- src/circles/Circles.sol | 2 +- src/circles/Demurrage.sol | 2 +- src/circles/DiscountedBalances.sol | 1 - src/lib/Math64x64.sol | 885 ----------------------------- test/utils/Approximation.sol | 2 +- 5 files changed, 3 insertions(+), 889 deletions(-) delete mode 100644 src/lib/Math64x64.sol diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index baf4829..59cebb2 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.24; +import {ABDKMath64x64 as Math64x64} from "lib/abdk-libraries-solidity/ABDKMath64x64.sol"; import "../errors/Errors.sol"; -import "../lib/Math64x64.sol"; import "./ERC1155.sol"; contract Circles is ERC1155, ICirclesErrors { diff --git a/src/circles/Demurrage.sol b/src/circles/Demurrage.sol index 98fd48a..17b4e20 100644 --- a/src/circles/Demurrage.sol +++ b/src/circles/Demurrage.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.24; +import {ABDKMath64x64 as Math64x64} from "lib/abdk-libraries-solidity/ABDKMath64x64.sol"; import "../errors/Errors.sol"; -import "../lib/Math64x64.sol"; contract Demurrage is ICirclesDemurrageErrors { // Type declarations diff --git a/src/circles/DiscountedBalances.sol b/src/circles/DiscountedBalances.sol index 47a6636..b8cffca 100644 --- a/src/circles/DiscountedBalances.sol +++ b/src/circles/DiscountedBalances.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.24; -import "../lib/Math64x64.sol"; import "./Demurrage.sol"; contract DiscountedBalances is Demurrage { diff --git a/src/lib/Math64x64.sol b/src/lib/Math64x64.sol deleted file mode 100644 index 08c23ed..0000000 --- a/src/lib/Math64x64.sol +++ /dev/null @@ -1,885 +0,0 @@ -// SPDX-License-Identifier: BSD-4-Clause -// solhint-disable -/* - * ABDK Math 64.64 Smart Contract Library. Copyright © 2019 by ABDK Consulting. - * Author: Mikhail Vladimirov - * - * from https://github.com/abdk-consulting/abdk-libraries-solidity - */ -pragma solidity ^0.8.4; - -/** - * Smart contract library of mathematical functions operating with signed - * 64.64-bit fixed point numbers. Signed 64.64-bit fixed point number is - * basically a simple fraction whose numerator is signed 128-bit integer and - * denominator is 2^64. As long as denominator is always the same, there is no - * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are - * represented by int128 type holding only the numerator. - */ -library Math64x64 { - /* - * Minimum value signed 64.64-bit fixed point number may have. - */ - int128 private constant MIN_64x64 = -0x80000000000000000000000000000000; - - /* - * Maximum value signed 64.64-bit fixed point number may have. - */ - int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - /** - * Convert signed 256-bit integer number into signed 64.64-bit fixed point - * number. Revert on overflow. - * - * @param x signed 256-bit integer number - * @return signed 64.64-bit fixed point number - */ - function fromInt(int256 x) internal pure returns (int128) { - unchecked { - require(x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF); - return int128(x << 64); - } - } - - /** - * Convert signed 64.64 fixed point number into signed 64-bit integer number - * rounding down. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64-bit integer number - */ - function toInt(int128 x) internal pure returns (int64) { - unchecked { - return int64(x >> 64); - } - } - - /** - * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point - * number. Revert on overflow. - * - * @param x unsigned 256-bit integer number - * @return signed 64.64-bit fixed point number - */ - function fromUInt(uint256 x) internal pure returns (int128) { - unchecked { - require(x <= 0x7FFFFFFFFFFFFFFF); - return int128(int256(x << 64)); - } - } - - /** - * Convert signed 64.64 fixed point number into unsigned 64-bit integer - * number rounding down. Revert on underflow. - * - * @param x signed 64.64-bit fixed point number - * @return unsigned 64-bit integer number - */ - function toUInt(int128 x) internal pure returns (uint64) { - unchecked { - require(x >= 0); - return uint64(uint128(x >> 64)); - } - } - - /** - * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point - * number rounding down. Revert on overflow. - * - * @param x signed 128.128-bin fixed point number - * @return signed 64.64-bit fixed point number - */ - function from128x128(int256 x) internal pure returns (int128) { - unchecked { - int256 result = x >> 64; - require(result >= MIN_64x64 && result <= MAX_64x64); - return int128(result); - } - } - - /** - * Convert signed 64.64 fixed point number into signed 128.128 fixed point - * number. - * - * @param x signed 64.64-bit fixed point number - * @return signed 128.128 fixed point number - */ - function to128x128(int128 x) internal pure returns (int256) { - unchecked { - return int256(x) << 64; - } - } - - /** - * Calculate x + y. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function add(int128 x, int128 y) internal pure returns (int128) { - unchecked { - int256 result = int256(x) + y; - require(result >= MIN_64x64 && result <= MAX_64x64); - return int128(result); - } - } - - /** - * Calculate x - y. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function sub(int128 x, int128 y) internal pure returns (int128) { - unchecked { - int256 result = int256(x) - y; - require(result >= MIN_64x64 && result <= MAX_64x64); - return int128(result); - } - } - - /** - * Calculate x * y rounding down. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function mul(int128 x, int128 y) internal pure returns (int128) { - unchecked { - int256 result = int256(x) * y >> 64; - require(result >= MIN_64x64 && result <= MAX_64x64); - return int128(result); - } - } - - /** - * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point - * number and y is signed 256-bit integer number. Revert on overflow. - * - * @param x signed 64.64 fixed point number - * @param y signed 256-bit integer number - * @return signed 256-bit integer number - */ - function muli(int128 x, int256 y) internal pure returns (int256) { - unchecked { - if (x == MIN_64x64) { - require( - y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - && y <= 0x1000000000000000000000000000000000000000000000000 - ); - return -y << 63; - } else { - bool negativeResult = false; - if (x < 0) { - x = -x; - negativeResult = true; - } - if (y < 0) { - y = -y; // We rely on overflow behavior here - negativeResult = !negativeResult; - } - uint256 absoluteResult = mulu(x, uint256(y)); - if (negativeResult) { - require(absoluteResult <= 0x8000000000000000000000000000000000000000000000000000000000000000); - return -int256(absoluteResult); // We rely on overflow behavior here - } else { - require(absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - return int256(absoluteResult); - } - } - } - } - - /** - * Calculate x * y rounding down, where x is signed 64.64 fixed point number - * and y is unsigned 256-bit integer number. Revert on overflow. - * - * @param x signed 64.64 fixed point number - * @param y unsigned 256-bit integer number - * @return unsigned 256-bit integer number - */ - function mulu(int128 x, uint256 y) internal pure returns (uint256) { - unchecked { - if (y == 0) return 0; - - require(x >= 0); - - uint256 lo = (uint256(int256(x)) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64; - uint256 hi = uint256(int256(x)) * (y >> 128); - - require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - hi <<= 64; - - require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo); - return hi + lo; - } - } - - /** - * Calculate x / y rounding towards zero. Revert on overflow or when y is - * zero. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function div(int128 x, int128 y) internal pure returns (int128) { - unchecked { - require(y != 0); - int256 result = (int256(x) << 64) / y; - require(result >= MIN_64x64 && result <= MAX_64x64); - return int128(result); - } - } - - /** - * Calculate x / y rounding towards zero, where x and y are signed 256-bit - * integer numbers. Revert on overflow or when y is zero. - * - * @param x signed 256-bit integer number - * @param y signed 256-bit integer number - * @return signed 64.64-bit fixed point number - */ - function divi(int256 x, int256 y) internal pure returns (int128) { - unchecked { - require(y != 0); - - bool negativeResult = false; - if (x < 0) { - x = -x; // We rely on overflow behavior here - negativeResult = true; - } - if (y < 0) { - y = -y; // We rely on overflow behavior here - negativeResult = !negativeResult; - } - uint128 absoluteResult = divuu(uint256(x), uint256(y)); - if (negativeResult) { - require(absoluteResult <= 0x80000000000000000000000000000000); - return -int128(absoluteResult); // We rely on overflow behavior here - } else { - require(absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - return int128(absoluteResult); // We rely on overflow behavior here - } - } - } - - /** - * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit - * integer numbers. Revert on overflow or when y is zero. - * - * @param x unsigned 256-bit integer number - * @param y unsigned 256-bit integer number - * @return signed 64.64-bit fixed point number - */ - function divu(uint256 x, uint256 y) internal pure returns (int128) { - unchecked { - require(y != 0); - uint128 result = divuu(x, y); - require(result <= uint128(MAX_64x64)); - return int128(result); - } - } - - /** - * Calculate -x. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function neg(int128 x) internal pure returns (int128) { - unchecked { - require(x != MIN_64x64); - return -x; - } - } - - /** - * Calculate |x|. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function abs(int128 x) internal pure returns (int128) { - unchecked { - require(x != MIN_64x64); - return x < 0 ? -x : x; - } - } - - /** - * Calculate 1 / x rounding towards zero. Revert on overflow or when x is - * zero. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function inv(int128 x) internal pure returns (int128) { - unchecked { - require(x != 0); - int256 result = int256(0x100000000000000000000000000000000) / x; - require(result >= MIN_64x64 && result <= MAX_64x64); - return int128(result); - } - } - - /** - * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function avg(int128 x, int128 y) internal pure returns (int128) { - unchecked { - return int128((int256(x) + int256(y)) >> 1); - } - } - - /** - * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down. - * Revert on overflow or in case x * y is negative. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function gavg(int128 x, int128 y) internal pure returns (int128) { - unchecked { - int256 m = int256(x) * int256(y); - require(m >= 0); - require(m < 0x4000000000000000000000000000000000000000000000000000000000000000); - return int128(sqrtu(uint256(m))); - } - } - - /** - * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number - * and y is unsigned 256-bit integer number. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @param y uint256 value - * @return signed 64.64-bit fixed point number - */ - function pow(int128 x, uint256 y) internal pure returns (int128) { - unchecked { - bool negative = x < 0 && y & 1 == 1; - - uint256 absX = uint128(x < 0 ? -x : x); - uint256 absResult; - absResult = 0x100000000000000000000000000000000; - - if (absX <= 0x10000000000000000) { - absX <<= 63; - while (y != 0) { - if (y & 0x1 != 0) { - absResult = absResult * absX >> 127; - } - absX = absX * absX >> 127; - - if (y & 0x2 != 0) { - absResult = absResult * absX >> 127; - } - absX = absX * absX >> 127; - - if (y & 0x4 != 0) { - absResult = absResult * absX >> 127; - } - absX = absX * absX >> 127; - - if (y & 0x8 != 0) { - absResult = absResult * absX >> 127; - } - absX = absX * absX >> 127; - - y >>= 4; - } - - absResult >>= 64; - } else { - uint256 absXShift = 63; - if (absX < 0x1000000000000000000000000) { - absX <<= 32; - absXShift -= 32; - } - if (absX < 0x10000000000000000000000000000) { - absX <<= 16; - absXShift -= 16; - } - if (absX < 0x1000000000000000000000000000000) { - absX <<= 8; - absXShift -= 8; - } - if (absX < 0x10000000000000000000000000000000) { - absX <<= 4; - absXShift -= 4; - } - if (absX < 0x40000000000000000000000000000000) { - absX <<= 2; - absXShift -= 2; - } - if (absX < 0x80000000000000000000000000000000) { - absX <<= 1; - absXShift -= 1; - } - - uint256 resultShift = 0; - while (y != 0) { - require(absXShift < 64); - - if (y & 0x1 != 0) { - absResult = absResult * absX >> 127; - resultShift += absXShift; - if (absResult > 0x100000000000000000000000000000000) { - absResult >>= 1; - resultShift += 1; - } - } - absX = absX * absX >> 127; - absXShift <<= 1; - if (absX >= 0x100000000000000000000000000000000) { - absX >>= 1; - absXShift += 1; - } - - y >>= 1; - } - - require(resultShift < 64); - absResult >>= 64 - resultShift; - } - int256 result = negative ? -int256(absResult) : int256(absResult); - require(result >= MIN_64x64 && result <= MAX_64x64); - return int128(result); - } - } - - /** - * Calculate sqrt (x) rounding down. Revert if x < 0. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function sqrt(int128 x) internal pure returns (int128) { - unchecked { - require(x >= 0); - return int128(sqrtu(uint256(int256(x)) << 64)); - } - } - - /** - * Calculate binary logarithm of x. Revert if x <= 0. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function log_2(int128 x) internal pure returns (int128) { - unchecked { - require(x > 0); - - int256 msb = 0; - int256 xc = x; - if (xc >= 0x10000000000000000) { - xc >>= 64; - msb += 64; - } - if (xc >= 0x100000000) { - xc >>= 32; - msb += 32; - } - if (xc >= 0x10000) { - xc >>= 16; - msb += 16; - } - if (xc >= 0x100) { - xc >>= 8; - msb += 8; - } - if (xc >= 0x10) { - xc >>= 4; - msb += 4; - } - if (xc >= 0x4) { - xc >>= 2; - msb += 2; - } - if (xc >= 0x2) msb += 1; // No need to shift xc anymore - - int256 result = msb - 64 << 64; - uint256 ux = uint256(int256(x)) << uint256(127 - msb); - for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) { - ux *= ux; - uint256 b = ux >> 255; - ux >>= 127 + b; - result += bit * int256(b); - } - - return int128(result); - } - } - - /** - * Calculate natural logarithm of x. Revert if x <= 0. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function ln(int128 x) internal pure returns (int128) { - unchecked { - require(x > 0); - - return int128(int256(uint256(int256(log_2(x))) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128)); - } - } - - /** - * Calculate binary exponent of x. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function exp_2(int128 x) internal pure returns (int128) { - unchecked { - require(x < 0x400000000000000000); // Overflow - - if (x < -0x400000000000000000) return 0; // Underflow - - uint256 result = 0x80000000000000000000000000000000; - - if (x & 0x8000000000000000 > 0) { - result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128; - } - if (x & 0x4000000000000000 > 0) { - result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128; - } - if (x & 0x2000000000000000 > 0) { - result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128; - } - if (x & 0x1000000000000000 > 0) { - result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128; - } - if (x & 0x800000000000000 > 0) { - result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128; - } - if (x & 0x400000000000000 > 0) { - result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128; - } - if (x & 0x200000000000000 > 0) { - result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128; - } - if (x & 0x100000000000000 > 0) { - result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128; - } - if (x & 0x80000000000000 > 0) { - result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128; - } - if (x & 0x40000000000000 > 0) { - result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128; - } - if (x & 0x20000000000000 > 0) { - result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128; - } - if (x & 0x10000000000000 > 0) { - result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128; - } - if (x & 0x8000000000000 > 0) { - result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128; - } - if (x & 0x4000000000000 > 0) { - result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128; - } - if (x & 0x2000000000000 > 0) { - result = result * 0x1000162E525EE054754457D5995292026 >> 128; - } - if (x & 0x1000000000000 > 0) { - result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128; - } - if (x & 0x800000000000 > 0) { - result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128; - } - if (x & 0x400000000000 > 0) { - result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128; - } - if (x & 0x200000000000 > 0) { - result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128; - } - if (x & 0x100000000000 > 0) { - result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128; - } - if (x & 0x80000000000 > 0) { - result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128; - } - if (x & 0x40000000000 > 0) { - result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128; - } - if (x & 0x20000000000 > 0) { - result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128; - } - if (x & 0x10000000000 > 0) { - result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128; - } - if (x & 0x8000000000 > 0) { - result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128; - } - if (x & 0x4000000000 > 0) { - result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128; - } - if (x & 0x2000000000 > 0) { - result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128; - } - if (x & 0x1000000000 > 0) { - result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128; - } - if (x & 0x800000000 > 0) { - result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128; - } - if (x & 0x400000000 > 0) { - result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128; - } - if (x & 0x200000000 > 0) { - result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128; - } - if (x & 0x100000000 > 0) { - result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128; - } - if (x & 0x80000000 > 0) { - result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128; - } - if (x & 0x40000000 > 0) { - result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128; - } - if (x & 0x20000000 > 0) { - result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128; - } - if (x & 0x10000000 > 0) { - result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128; - } - if (x & 0x8000000 > 0) { - result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128; - } - if (x & 0x4000000 > 0) { - result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128; - } - if (x & 0x2000000 > 0) { - result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128; - } - if (x & 0x1000000 > 0) { - result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128; - } - if (x & 0x800000 > 0) { - result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128; - } - if (x & 0x400000 > 0) { - result = result * 0x100000000002C5C85FDF477B662B26945 >> 128; - } - if (x & 0x200000 > 0) { - result = result * 0x10000000000162E42FEFA3AE53369388C >> 128; - } - if (x & 0x100000 > 0) { - result = result * 0x100000000000B17217F7D1D351A389D40 >> 128; - } - if (x & 0x80000 > 0) { - result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128; - } - if (x & 0x40000 > 0) { - result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128; - } - if (x & 0x20000 > 0) { - result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128; - } - if (x & 0x10000 > 0) { - result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128; - } - if (x & 0x8000 > 0) { - result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128; - } - if (x & 0x4000 > 0) { - result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128; - } - if (x & 0x2000 > 0) { - result = result * 0x1000000000000162E42FEFA39F02B772C >> 128; - } - if (x & 0x1000 > 0) { - result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128; - } - if (x & 0x800 > 0) { - result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128; - } - if (x & 0x400 > 0) { - result = result * 0x100000000000002C5C85FDF473DEA871F >> 128; - } - if (x & 0x200 > 0) { - result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128; - } - if (x & 0x100 > 0) { - result = result * 0x100000000000000B17217F7D1CF79E949 >> 128; - } - if (x & 0x80 > 0) { - result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128; - } - if (x & 0x40 > 0) { - result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128; - } - if (x & 0x20 > 0) { - result = result * 0x100000000000000162E42FEFA39EF366F >> 128; - } - if (x & 0x10 > 0) { - result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128; - } - if (x & 0x8 > 0) { - result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128; - } - if (x & 0x4 > 0) { - result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128; - } - if (x & 0x2 > 0) { - result = result * 0x1000000000000000162E42FEFA39EF358 >> 128; - } - if (x & 0x1 > 0) { - result = result * 0x10000000000000000B17217F7D1CF79AB >> 128; - } - - result >>= uint256(int256(63 - (x >> 64))); - require(result <= uint256(int256(MAX_64x64))); - - return int128(int256(result)); - } - } - - /** - * Calculate natural exponent of x. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function exp(int128 x) internal pure returns (int128) { - unchecked { - require(x < 0x400000000000000000); // Overflow - - if (x < -0x400000000000000000) return 0; // Underflow - - return exp_2(int128(int256(x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128)); - } - } - - /** - * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit - * integer numbers. Revert on overflow or when y is zero. - * - * @param x unsigned 256-bit integer number - * @param y unsigned 256-bit integer number - * @return unsigned 64.64-bit fixed point number - */ - function divuu(uint256 x, uint256 y) private pure returns (uint128) { - unchecked { - require(y != 0); - - uint256 result; - - if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) { - result = (x << 64) / y; - } else { - uint256 msb = 192; - uint256 xc = x >> 192; - if (xc >= 0x100000000) { - xc >>= 32; - msb += 32; - } - if (xc >= 0x10000) { - xc >>= 16; - msb += 16; - } - if (xc >= 0x100) { - xc >>= 8; - msb += 8; - } - if (xc >= 0x10) { - xc >>= 4; - msb += 4; - } - if (xc >= 0x4) { - xc >>= 2; - msb += 2; - } - if (xc >= 0x2) msb += 1; // No need to shift xc anymore - - result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1); - require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - uint256 hi = result * (y >> 128); - uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - uint256 xh = x >> 192; - uint256 xl = x << 64; - - if (xl < lo) xh -= 1; - xl -= lo; // We rely on overflow behavior here - lo = hi << 128; - if (xl < lo) xh -= 1; - xl -= lo; // We rely on overflow behavior here - - assert(xh == hi >> 128); - - result += xl / y; - } - - require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - return uint128(result); - } - } - - /** - * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer - * number. - * - * @param x unsigned 256-bit integer number - * @return unsigned 128-bit integer number - */ - function sqrtu(uint256 x) private pure returns (uint128) { - unchecked { - if (x == 0) { - return 0; - } else { - uint256 xx = x; - uint256 r = 1; - if (xx >= 0x100000000000000000000000000000000) { - xx >>= 128; - r <<= 64; - } - if (xx >= 0x10000000000000000) { - xx >>= 64; - r <<= 32; - } - if (xx >= 0x100000000) { - xx >>= 32; - r <<= 16; - } - if (xx >= 0x10000) { - xx >>= 16; - r <<= 8; - } - if (xx >= 0x100) { - xx >>= 8; - r <<= 4; - } - if (xx >= 0x10) { - xx >>= 4; - r <<= 2; - } - if (xx >= 0x8) r <<= 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; // Seven iterations should be enough - uint256 r1 = x / r; - return uint128(r < r1 ? r : r1); - } - } - } -} diff --git a/test/utils/Approximation.sol b/test/utils/Approximation.sol index ba444d7..dcfb090 100644 --- a/test/utils/Approximation.sol +++ b/test/utils/Approximation.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.13; -import "../../src/lib/Math64x64.sol"; +import {ABDKMath64x64 as Math64x64} from "lib/abdk-libraries-solidity/ABDKMath64x64.sol"; contract Approximation { // Constants From 160ddb1fd5c8b4ab7c1ab048e14326a03f85f240 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 7 Aug 2024 23:41:07 +0200 Subject: [PATCH 20/25] (Hub): correct function docs to remove old param --- src/hub/Hub.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 21482c8..f325a7f 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -690,7 +690,6 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * this must reference the index of the stream in the streams array, starting from 1) * @param _coordinates unpacked array of coordinates of the flow edges, with 3 coordinates per flow edge: * Circles identifier being transfered, sender, receiver, each a uint16 referencing the flow vertex. - * @param _closedPath boolean indicating whether the path is a closed path or not */ function _verifyFlowMatrix( address[] calldata _flowVertices, From 1cf9ac55677b82bbd9f6cac2523eb6e186c5c355 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 8 Aug 2024 11:50:33 +0200 Subject: [PATCH 21/25] (hub): (saves 127kB) revert memory/storage optimisations in favor of reducing compile size --- src/hub/Hub.sol | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index fad09de..6aa3846 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -437,15 +437,14 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // Only human can call stop. revert CirclesHubMustBeHuman(msg.sender, 2); } - uint96 lastMintTime = mintTimes[msg.sender].lastMintTime; + MintTime storage mintTime = mintTimes[msg.sender]; // check if already stopped - if (lastMintTime == INDEFINITE_FUTURE) { + if (mintTime.lastMintTime == INDEFINITE_FUTURE) { return; } // stop future mints of personal Circles // by setting the last mint time to indefinite future. - lastMintTime = INDEFINITE_FUTURE; - mintTimes[msg.sender].lastMintTime = lastMintTime; + mintTime.lastMintTime = INDEFINITE_FUTURE; emit Stopped(msg.sender); } @@ -459,8 +458,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // Only personal Circles can have a status of boolean stopped. revert CirclesHubMustBeHuman(_human, 3); } - uint96 lastMintTime = mintTimes[msg.sender].lastMintTime; - return (lastMintTime == INDEFINITE_FUTURE); + MintTime storage mintTime = mintTimes[msg.sender]; + return (mintTime.lastMintTime == INDEFINITE_FUTURE); } /** @@ -613,7 +612,6 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { } /** - * @notice Returns true if the flow to the receiver is permitted. * The receiver must trust the Circles being sent, and the Circles avatar associated with * the Circles must trust the receiver. @@ -945,10 +943,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // set the last mint time to the current timestamp for invited human // and register the v1 Circles contract status v1CirclesStatus = _avatarV1CirclesStatus(_human); - MintTime memory mintTime = mintTimes[_human]; + MintTime storage mintTime = mintTimes[_human]; mintTime.mintV1Status = v1CirclesStatus; mintTime.lastMintTime = uint96(block.timestamp); - mintTimes[_human] = mintTime; // trust self indefinitely, cannot be altered later _trust(_human, _human, INDEFINITE_FUTURE); @@ -1066,7 +1063,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * @param _mintV1Status Mint status of the v1 Circles contract. */ function _updateMintV1Status(address _human, address _mintV1Status) internal { - MintTime memory mintTime = mintTimes[_human]; + MintTime storage mintTime = mintTimes[_human]; // precautionary check to ensure that the last mint time is already set // as this marks whether an avatar is registered as human or not if (mintTime.lastMintTime == 0) { @@ -1078,7 +1075,6 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { if (mintTime.mintV1Status != _mintV1Status) { mintTime.mintV1Status = _mintV1Status; mintTime.lastMintTime = uint96(block.timestamp); - mintTimes[_human] = mintTime; } } From 976473a713ef19772eab08a50eee4f391f97334e Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 8 Aug 2024 17:30:05 +0200 Subject: [PATCH 22/25] (Circles, InflationaryOperator): move inflationary helper functions out of Hub to operator to save compile space in hub --- src/circles/Circles.sol | 61 ------------------- src/circles/InflationaryOperator.sol | 91 ++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 61 deletions(-) create mode 100644 src/circles/InflationaryOperator.sol diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 1efb159..45d2c63 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -75,67 +75,6 @@ contract Circles is ERC1155, ICirclesErrors { DiscountedBalances(_inflation_day_zero) {} - // Public functions - - /** - * Inflationary balance of an account for a Circles identifier. Careful, - * calculating the inflationary balance can introduce numerical errors - * in the least significant digits (order of few attoCircles). - * @param _account Address for which the balance is queried. - * @param _id Circles identifier for which the balance is queried. - */ - function inflationaryBalanceOf(address _account, uint256 _id) public view returns (uint256) { - return _inflationaryBalanceOf(_account, _id); - } - - /** - * @notice safeInflationaryTransferFrom transfers Circles from one address to another by specifying inflationary units. - * @param _from Address from which the Circles are transferred. - * @param _to Address to which the Circles are transferred. - * @param _id Circles indentifier for which the Circles are transferred. - * @param _inflationaryValue Inflationary value of the Circles transferred. - * @param _data Data to pass to the receiver. - */ - function safeInflationaryTransferFrom( - address _from, - address _to, - uint256 _id, - uint256 _inflationaryValue, - bytes memory _data - ) public { - address sender = _msgSender(); - if (_from != sender && !isApprovedForAll(_from, sender)) { - revert ERC1155MissingApprovalForAll(sender, _from); - } - // convert inflationary value to todays demurrage value - uint256 value = convertInflationaryToDemurrageValue(_inflationaryValue, day(block.timestamp)); - _safeTransferFrom(_from, _to, _id, value, _data); - } - - /** - * @notice safeInflationaryBatchTransferFrom transfers Circles from one address to another by specifying inflationary units. - * @param _from Address from which the Circles are transferred. - * @param _to Address to which the Circles are transferred. - * @param _ids Batch of Circles identifiers for which the Circles are transferred. - * @param _inflationaryValues Batch of inflationary values of the Circles transferred. - * @param _data Data to pass to the receiver. - */ - function safeInflationaryBatchTransferFrom( - address _from, - address _to, - uint256[] memory _ids, - uint256[] memory _inflationaryValues, - bytes memory _data - ) public { - address sender = _msgSender(); - if (_from != sender && !isApprovedForAll(_from, sender)) { - revert ERC1155MissingApprovalForAll(sender, _from); - } - uint64 today = day(block.timestamp); - uint256[] memory values = convertBatchInflationaryToDemurrageValues(_inflationaryValues, today); - _safeBatchTransferFrom(_from, _to, _ids, values, _data); - } - // Internal functions /** diff --git a/src/circles/InflationaryOperator.sol b/src/circles/InflationaryOperator.sol new file mode 100644 index 0000000..3c7114c --- /dev/null +++ b/src/circles/InflationaryOperator.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.24; + +import "../hub/IHub.sol"; +import "./Demurrage.sol"; + +contract InflationaryCirclesOperator is Demurrage { + // Storage + + IHubV2 public hub; + + // Constructor + + constructor(IHubV2 _hub) { + hub = _hub; + } + + // Public functions + + /** + * Inflationary balance of an account for a Circles identifier. Careful, + * calculating the inflationary balance can introduce numerical errors + * in the least significant digits (order of few attoCircles). + * @param _account Address for which the balance is queried. + * @param _id Circles identifier for which the balance is queried. + */ + function inflationaryBalanceOf(address _account, uint256 _id) public view returns (uint256) { + return _inflationaryBalanceOf(_account, _id); + } + + // /** + // * @notice safeInflationaryTransferFrom transfers Circles from one address to another by specifying inflationary units. + // * @param _from Address from which the Circles are transferred. + // * @param _to Address to which the Circles are transferred. + // * @param _id Circles indentifier for which the Circles are transferred. + // * @param _inflationaryValue Inflationary value of the Circles transferred. + // * @param _data Data to pass to the receiver. + // */ + // function safeInflationaryTransferFrom( + // address _from, + // address _to, + // uint256 _id, + // uint256 _inflationaryValue, + // bytes memory _data + // ) public { + // address sender = _msgSender(); + // if (_from != sender && !isApprovedForAll(_from, sender)) { + // revert ERC1155MissingApprovalForAll(sender, _from); + // } + // // convert inflationary value to todays demurrage value + // uint256 value = convertInflationaryToDemurrageValue(_inflationaryValue, day(block.timestamp)); + // _safeTransferFrom(_from, _to, _id, value, _data); + // } + + // /** + // * @notice safeInflationaryBatchTransferFrom transfers Circles from one address to another by specifying inflationary units. + // * @param _from Address from which the Circles are transferred. + // * @param _to Address to which the Circles are transferred. + // * @param _ids Batch of Circles identifiers for which the Circles are transferred. + // * @param _inflationaryValues Batch of inflationary values of the Circles transferred. + // * @param _data Data to pass to the receiver. + // */ + // function safeInflationaryBatchTransferFrom( + // address _from, + // address _to, + // uint256[] memory _ids, + // uint256[] memory _inflationaryValues, + // bytes memory _data + // ) public { + // address sender = _msgSender(); + // if (_from != sender && !isApprovedForAll(_from, sender)) { + // revert ERC1155MissingApprovalForAll(sender, _from); + // } + // uint64 today = day(block.timestamp); + // uint256[] memory values = convertBatchInflationaryToDemurrageValues(_inflationaryValues, today); + // _safeBatchTransferFrom(_from, _to, _ids, values, _data); + // } + + // Internal functions + + /** + * @dev Calculate the inflationary balance of a discounted balance + * @param _account Address of the account to calculate the balance of + * @param _id Circles identifier for which to calculate the balance + */ + function _inflationaryBalanceOf(address _account, uint256 _id) internal view returns (uint256) { + // retrieve the balance in demurrage units (of today) + uint256 balance = hub.balanceOf(_account, _id); + return _calculateInflationaryBalance(balance, day(block.timestamp)); + } +} From 7788ef82b9f43b84b7c13a9f35b2ebff6b507cc0 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 8 Aug 2024 17:43:47 +0200 Subject: [PATCH 23/25] (InflationaryCirclesOperator): implement the safe(Batch)TransferFrom for inflationary values in the operator --- src/circles/InflationaryOperator.sol | 98 +++++++++++++++------------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/src/circles/InflationaryOperator.sol b/src/circles/InflationaryOperator.sol index 3c7114c..7097679 100644 --- a/src/circles/InflationaryOperator.sol +++ b/src/circles/InflationaryOperator.sol @@ -9,6 +9,20 @@ contract InflationaryCirclesOperator is Demurrage { IHubV2 public hub; + // Errors + + error InflationaryCirclesOperatorOnlyActOnBalancesOfSender(address sender, address from); + + // Modifier + + modifier OnlyActOnBalancesOfSender(address _from) { + if (_from != msg.sender) { + // only accept requests that act on the balances of msg.sender + revert InflationaryCirclesOperatorOnlyActOnBalancesOfSender(msg.sender, _from); + } + _; + } + // Constructor constructor(IHubV2 _hub) { @@ -28,53 +42,45 @@ contract InflationaryCirclesOperator is Demurrage { return _inflationaryBalanceOf(_account, _id); } - // /** - // * @notice safeInflationaryTransferFrom transfers Circles from one address to another by specifying inflationary units. - // * @param _from Address from which the Circles are transferred. - // * @param _to Address to which the Circles are transferred. - // * @param _id Circles indentifier for which the Circles are transferred. - // * @param _inflationaryValue Inflationary value of the Circles transferred. - // * @param _data Data to pass to the receiver. - // */ - // function safeInflationaryTransferFrom( - // address _from, - // address _to, - // uint256 _id, - // uint256 _inflationaryValue, - // bytes memory _data - // ) public { - // address sender = _msgSender(); - // if (_from != sender && !isApprovedForAll(_from, sender)) { - // revert ERC1155MissingApprovalForAll(sender, _from); - // } - // // convert inflationary value to todays demurrage value - // uint256 value = convertInflationaryToDemurrageValue(_inflationaryValue, day(block.timestamp)); - // _safeTransferFrom(_from, _to, _id, value, _data); - // } + /** + * @notice safeInflationaryTransferFrom transfers Circles from one address to another by specifying inflationary units. + * @param _from Address from which the Circles are transferred. + * @param _to Address to which the Circles are transferred. + * @param _id Circles indentifier for which the Circles are transferred. + * @param _inflationaryValue Inflationary value of the Circles transferred. + * @param _data Data to pass to the receiver. + */ + function safeInflationaryTransferFrom( + address _from, + address _to, + uint256 _id, + uint256 _inflationaryValue, + bytes memory _data + ) public OnlyActOnBalancesOfSender(_from) { + // convert inflationary value to todays demurrage value + uint256 value = convertInflationaryToDemurrageValue(_inflationaryValue, day(block.timestamp)); + // if from has this operator authorized, it can call ERC1155:safeTransferFrom + hub.safeTransferFrom(_from, _to, _id, value, _data); + } - // /** - // * @notice safeInflationaryBatchTransferFrom transfers Circles from one address to another by specifying inflationary units. - // * @param _from Address from which the Circles are transferred. - // * @param _to Address to which the Circles are transferred. - // * @param _ids Batch of Circles identifiers for which the Circles are transferred. - // * @param _inflationaryValues Batch of inflationary values of the Circles transferred. - // * @param _data Data to pass to the receiver. - // */ - // function safeInflationaryBatchTransferFrom( - // address _from, - // address _to, - // uint256[] memory _ids, - // uint256[] memory _inflationaryValues, - // bytes memory _data - // ) public { - // address sender = _msgSender(); - // if (_from != sender && !isApprovedForAll(_from, sender)) { - // revert ERC1155MissingApprovalForAll(sender, _from); - // } - // uint64 today = day(block.timestamp); - // uint256[] memory values = convertBatchInflationaryToDemurrageValues(_inflationaryValues, today); - // _safeBatchTransferFrom(_from, _to, _ids, values, _data); - // } + /** + * @notice safeInflationaryBatchTransferFrom transfers Circles from one address to another by specifying inflationary units. + * @param _from Address from which the Circles are transferred. + * @param _to Address to which the Circles are transferred. + * @param _ids Batch of Circles identifiers for which the Circles are transferred. + * @param _inflationaryValues Batch of inflationary values of the Circles transferred. + * @param _data Data to pass to the receiver. + */ + function safeInflationaryBatchTransferFrom( + address _from, + address _to, + uint256[] memory _ids, + uint256[] memory _inflationaryValues, + bytes memory _data + ) public OnlyActOnBalancesOfSender(_from) { + uint256[] memory values = convertBatchInflationaryToDemurrageValues(_inflationaryValues, day(block.timestamp)); + hub.safeBatchTransferFrom(_from, _to, _ids, values, _data); + } // Internal functions From 1d343b7fa8501c0347568df9318414f630cd585d Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 8 Aug 2024 17:59:31 +0200 Subject: [PATCH 24/25] (version, Hub): name version rc-v0.3.5-alpha; re-add name, symbol RINGS to hub --- script/deployments/package.json | 2 +- src/hub/Hub.sol | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/script/deployments/package.json b/script/deployments/package.json index 94329c6..e9f010b 100644 --- a/script/deployments/package.json +++ b/script/deployments/package.json @@ -1,6 +1,6 @@ { "name": "deploy-circles", - "version": "0.3.4-alpha", + "version": "rc-0.3.5-alpha", "type": "module", "dependencies": { "dotenv": "^16.4.5", diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 6aa3846..b0ce135 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -41,17 +41,17 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // State variables - // /** - // * @notice The global name of Circles. - // * todo, change this to "Circles" for the production deployment - // */ - // string public name = "Rings"; - - // /** - // * @notice The global symbol ticker for Circles. - // * todo, change this to "CRC" for the production deployment - // */ - // string public symbol = "RING"; + /** + * @notice The global name of Circles. + * todo, change this to "Circles" for the production deployment + */ + string public name = "Rings"; + + /** + * @notice The global symbol ticker for Circles. + * todo, change this to "CRC" for the production deployment + */ + string public symbol = "RING"; /** * @notice The Hub v1 contract address. From ea9b7ad47399183e239acafa541bcd3659f84fc4 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 8 Aug 2024 19:05:04 +0200 Subject: [PATCH 25/25] (deploy): deploy details release candidate rc-v0.3.5-alpha as RINGS test integration on GC --- ...ts-rc-0.3.5-alpha-1d343b7-240808-180634.txt | 9 +++++++++ ...do-rc-0.3.5-alpha-1d343b7-240808-180634.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 + ...ts-rc-0.3.5-alpha-1d343b7-240808-183621.txt | 9 +++++++++ ...do-rc-0.3.5-alpha-1d343b7-240808-183621.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 + script/deployments/chiadoDeploy.sh | 2 +- script/deployments/gnosisChainDeploy.sh | 2 +- .../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.5-alpha-1d343b7-240808-185913.txt | 9 +++++++++ ...in-rc-0.3.5-alpha-1d343b7-240808-185913.log | 18 ++++++++++++++++++ 35 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/chiado-artefacts-rc-0.3.5-alpha-1d343b7-240808-180634.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/chiado-rc-0.3.5-alpha-1d343b7-240808-180634.log create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_BaseGroupMintPolicy.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_ERC20Lift.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_Hub.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyDemurrageERC20.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyInflationaryERC20.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyStandardVault.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_Migration.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_NameRegistry.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_StandardTreasury.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/chiado-artefacts-rc-0.3.5-alpha-1d343b7-240808-183621.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/chiado-rc-0.3.5-alpha-1d343b7-240808-183621.log create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_BaseGroupMintPolicy.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_ERC20Lift.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_Hub.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyDemurrageERC20.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyInflationaryERC20.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyStandardVault.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_Migration.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_NameRegistry.txt create mode 100644 script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_StandardTreasury.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_BaseGroupMintPolicy.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_ERC20Lift.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_Hub.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyDemurrageERC20.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyInflationaryERC20.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyStandardVault.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_Migration.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_NameRegistry.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_StandardTreasury.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/gnosischain-artefacts-rc-0.3.5-alpha-1d343b7-240808-185913.txt create mode 100644 script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913.log diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/chiado-artefacts-rc-0.3.5-alpha-1d343b7-240808-180634.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/chiado-artefacts-rc-0.3.5-alpha-1d343b7-240808-180634.txt new file mode 100644 index 0000000..77e0f21 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/chiado-artefacts-rc-0.3.5-alpha-1d343b7-240808-180634.txt @@ -0,0 +1,9 @@ +{"contractName":"Hub","deployedAddress":"0x4360449bAfbA60660125e4306960AaF23Dc90aaa","sourcePath":"src/hub/Hub.sol:Hub","constructor-args":"0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0x92132109fAEFb69a307c53Ce3506CA9DAF12c96c 0x3d22c0db967d4eF3A135AAF37b93D2DA1E631AF7 0xD1a83E3ae4817096Ff448BE2f0C4432B34bCf33D 0x7Fb40eEcC73F7ac2F24B43f1A827A0e8F98FEa34 1675209600 31540000 https://fallback.aboutcircles.com/v1/circles/{id}.json","argumentsFile":"constructorArgs_Hub.txt"} +{"contractName":"Migration","deployedAddress":"0x3d22c0db967d4eF3A135AAF37b93D2DA1E631AF7","sourcePath":"src/migration/Migration.sol:Migration","constructor-args":"0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0x4360449bAfbA60660125e4306960AaF23Dc90aaa 1675209600","argumentsFile":"constructorArgs_Migration.txt"} +{"contractName":"NameRegistry","deployedAddress":"0x92132109fAEFb69a307c53Ce3506CA9DAF12c96c","sourcePath":"src/names/NameRegistry.sol:NameRegistry","constructor-args":"0x4360449bAfbA60660125e4306960AaF23Dc90aaa","argumentsFile":"constructorArgs_NameRegistry.txt"} +{"contractName":"ERC20Lift","deployedAddress":"0xD1a83E3ae4817096Ff448BE2f0C4432B34bCf33D","sourcePath":"src/lift/ERC20Lift.sol:ERC20Lift","constructor-args":"0x4360449bAfbA60660125e4306960AaF23Dc90aaa 0x92132109fAEFb69a307c53Ce3506CA9DAF12c96c 0x3da7E15b21fFA1355e74eD0b4C98Cc2A8ab37772 0xeaBE5f7911e2A084fb57Ef26F1a159c1219215Dc","argumentsFile":"constructorArgs_ERC20Lift.txt"} +{"contractName":"StandardTreasury","deployedAddress":"0x7Fb40eEcC73F7ac2F24B43f1A827A0e8F98FEa34","sourcePath":"src/treasury/StandardTreasury.sol:StandardTreasury","constructor-args":"0x4360449bAfbA60660125e4306960AaF23Dc90aaa 0xbFE9AE97853cCdCB11C954337237bc3492D2e618","argumentsFile":"constructorArgs_StandardTreasury.txt"} +{"contractName":"BaseGroupMintPolicy","deployedAddress":"0xc96F273676278105cC6105C1594DF4C20A1B8c34","sourcePath":"src/groups/BaseMintPolicy.sol:MintPolicy","constructor-args":"","argumentsFile":"constructorArgs_BaseGroupMintPolicy.txt"} +{"contractName":"MastercopyDemurrageERC20","deployedAddress":"0x3da7E15b21fFA1355e74eD0b4C98Cc2A8ab37772","sourcePath":"src/lift/DemurrageCircles.sol:DemurrageCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyDemurrageERC20.txt"} +{"contractName":"MastercopyInflationaryERC20","deployedAddress":"0xeaBE5f7911e2A084fb57Ef26F1a159c1219215Dc","sourcePath":"src/lift/InflationaryCircles.sol:InflationaryCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyInflationaryERC20.txt"} +{"contractName":"MastercopyStandardVault","deployedAddress":"0xbFE9AE97853cCdCB11C954337237bc3492D2e618","sourcePath":"src/treasury/StandardVault.sol:StandardVault","constructor-args":"","argumentsFile":"constructorArgs_MastercopyStandardVault.txt"} diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/chiado-rc-0.3.5-alpha-1d343b7-240808-180634.log b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/chiado-rc-0.3.5-alpha-1d343b7-240808-180634.log new file mode 100644 index 0000000..243f510 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/chiado-rc-0.3.5-alpha-1d343b7-240808-180634.log @@ -0,0 +1,18 @@ +Chiado deployment +================= +Deployment Date: 2024-08-08 18:06:34 +Version: rc-0.3.5-alpha +Git Commit: 1d343b7fa8501c0347568df9318414f630cd585d +Deployer Address: 0x7619F26728Ced663E50E578EB6ff42430931564c, Intitial nonce: 140 +Compiler Version: v0.8.23+commit.f704f362 + +Deployed Contracts: +Hub: 0x4360449bAfbA60660125e4306960AaF23Dc90aaa +Migration: 0x3d22c0db967d4eF3A135AAF37b93D2DA1E631AF7 +NameRegistry: 0x92132109fAEFb69a307c53Ce3506CA9DAF12c96c +ERC20Lift: 0xD1a83E3ae4817096Ff448BE2f0C4432B34bCf33D +StandardTreasury: 0x7Fb40eEcC73F7ac2F24B43f1A827A0e8F98FEa34 +BaseGroupMintPolicy: 0xc96F273676278105cC6105C1594DF4C20A1B8c34 +MastercopyDemurrageERC20: 0x3da7E15b21fFA1355e74eD0b4C98Cc2A8ab37772 +MastercopyInflationaryERC20: 0xeaBE5f7911e2A084fb57Ef26F1a159c1219215Dc +MastercopyStandardVault: 0xbFE9AE97853cCdCB11C954337237bc3492D2e618 diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_BaseGroupMintPolicy.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_BaseGroupMintPolicy.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_BaseGroupMintPolicy.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_ERC20Lift.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_ERC20Lift.txt new file mode 100644 index 0000000..62b4555 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_ERC20Lift.txt @@ -0,0 +1 @@ +0x4360449bAfbA60660125e4306960AaF23Dc90aaa 0x92132109fAEFb69a307c53Ce3506CA9DAF12c96c 0x3da7E15b21fFA1355e74eD0b4C98Cc2A8ab37772 0xeaBE5f7911e2A084fb57Ef26F1a159c1219215Dc diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_Hub.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_Hub.txt new file mode 100644 index 0000000..8a4e5ba --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_Hub.txt @@ -0,0 +1 @@ +0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0x92132109fAEFb69a307c53Ce3506CA9DAF12c96c 0x3d22c0db967d4eF3A135AAF37b93D2DA1E631AF7 0xD1a83E3ae4817096Ff448BE2f0C4432B34bCf33D 0x7Fb40eEcC73F7ac2F24B43f1A827A0e8F98FEa34 1675209600 31540000 https://fallback.aboutcircles.com/v1/circles/{id}.json diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyDemurrageERC20.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyDemurrageERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyDemurrageERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyInflationaryERC20.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyInflationaryERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyInflationaryERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyStandardVault.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyStandardVault.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_MastercopyStandardVault.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_Migration.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_Migration.txt new file mode 100644 index 0000000..de69d48 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_Migration.txt @@ -0,0 +1 @@ +0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0x4360449bAfbA60660125e4306960AaF23Dc90aaa 1675209600 diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_NameRegistry.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_NameRegistry.txt new file mode 100644 index 0000000..d4ca7da --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_NameRegistry.txt @@ -0,0 +1 @@ +0x4360449bAfbA60660125e4306960AaF23Dc90aaa diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_StandardTreasury.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_StandardTreasury.txt new file mode 100644 index 0000000..e430e97 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-180634/constructorArgs_StandardTreasury.txt @@ -0,0 +1 @@ +0x4360449bAfbA60660125e4306960AaF23Dc90aaa 0xbFE9AE97853cCdCB11C954337237bc3492D2e618 diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/chiado-artefacts-rc-0.3.5-alpha-1d343b7-240808-183621.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/chiado-artefacts-rc-0.3.5-alpha-1d343b7-240808-183621.txt new file mode 100644 index 0000000..d73ea3b --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/chiado-artefacts-rc-0.3.5-alpha-1d343b7-240808-183621.txt @@ -0,0 +1,9 @@ +{"contractName":"Hub","deployedAddress":"0xEddc960D3c78692BF38577054cb0a35114AE35e0","sourcePath":"src/hub/Hub.sol:Hub","constructor-args":"0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0x5525cbF9ad01a4E805ed1b40723D6377b336eCcf 0x8C9BeAccb6b7DBd3AeffB5D77cab36b62Fe98882 0xd6407bc654a4de9b044b84dCfF9B77F0250fCba3 0x66A024F2055fa84b40f27c2f3Eb68A848276A641 1675209600 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json","argumentsFile":"constructorArgs_Hub.txt"} +{"contractName":"Migration","deployedAddress":"0x8C9BeAccb6b7DBd3AeffB5D77cab36b62Fe98882","sourcePath":"src/migration/Migration.sol:Migration","constructor-args":"0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0xEddc960D3c78692BF38577054cb0a35114AE35e0 1675209600","argumentsFile":"constructorArgs_Migration.txt"} +{"contractName":"NameRegistry","deployedAddress":"0x5525cbF9ad01a4E805ed1b40723D6377b336eCcf","sourcePath":"src/names/NameRegistry.sol:NameRegistry","constructor-args":"0xEddc960D3c78692BF38577054cb0a35114AE35e0","argumentsFile":"constructorArgs_NameRegistry.txt"} +{"contractName":"ERC20Lift","deployedAddress":"0xd6407bc654a4de9b044b84dCfF9B77F0250fCba3","sourcePath":"src/lift/ERC20Lift.sol:ERC20Lift","constructor-args":"0xEddc960D3c78692BF38577054cb0a35114AE35e0 0x5525cbF9ad01a4E805ed1b40723D6377b336eCcf 0xB3B6950411bE5b9411CdE616B669204A24569bD5 0xB04Ad230CBD53Faf0888de2e131467BD933F8237","argumentsFile":"constructorArgs_ERC20Lift.txt"} +{"contractName":"StandardTreasury","deployedAddress":"0x66A024F2055fa84b40f27c2f3Eb68A848276A641","sourcePath":"src/treasury/StandardTreasury.sol:StandardTreasury","constructor-args":"0xEddc960D3c78692BF38577054cb0a35114AE35e0 0xb2bEcDfEB4afcaB94Fa05b3822D35cD401C7897A","argumentsFile":"constructorArgs_StandardTreasury.txt"} +{"contractName":"BaseGroupMintPolicy","deployedAddress":"0xaD49f877021c73d00bE142b135c9AA67f0D8e9c6","sourcePath":"src/groups/BaseMintPolicy.sol:MintPolicy","constructor-args":"","argumentsFile":"constructorArgs_BaseGroupMintPolicy.txt"} +{"contractName":"MastercopyDemurrageERC20","deployedAddress":"0xB3B6950411bE5b9411CdE616B669204A24569bD5","sourcePath":"src/lift/DemurrageCircles.sol:DemurrageCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyDemurrageERC20.txt"} +{"contractName":"MastercopyInflationaryERC20","deployedAddress":"0xB04Ad230CBD53Faf0888de2e131467BD933F8237","sourcePath":"src/lift/InflationaryCircles.sol:InflationaryCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyInflationaryERC20.txt"} +{"contractName":"MastercopyStandardVault","deployedAddress":"0xb2bEcDfEB4afcaB94Fa05b3822D35cD401C7897A","sourcePath":"src/treasury/StandardVault.sol:StandardVault","constructor-args":"","argumentsFile":"constructorArgs_MastercopyStandardVault.txt"} diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/chiado-rc-0.3.5-alpha-1d343b7-240808-183621.log b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/chiado-rc-0.3.5-alpha-1d343b7-240808-183621.log new file mode 100644 index 0000000..cafc325 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/chiado-rc-0.3.5-alpha-1d343b7-240808-183621.log @@ -0,0 +1,18 @@ +Chiado deployment +================= +Deployment Date: 2024-08-08 18:36:21 +Version: rc-0.3.5-alpha +Git Commit: 1d343b7fa8501c0347568df9318414f630cd585d +Deployer Address: 0x7619F26728Ced663E50E578EB6ff42430931564c, Intitial nonce: 149 +Compiler Version: v0.8.23+commit.f704f362 + +Deployed Contracts: +Hub: 0xEddc960D3c78692BF38577054cb0a35114AE35e0 +Migration: 0x8C9BeAccb6b7DBd3AeffB5D77cab36b62Fe98882 +NameRegistry: 0x5525cbF9ad01a4E805ed1b40723D6377b336eCcf +ERC20Lift: 0xd6407bc654a4de9b044b84dCfF9B77F0250fCba3 +StandardTreasury: 0x66A024F2055fa84b40f27c2f3Eb68A848276A641 +BaseGroupMintPolicy: 0xaD49f877021c73d00bE142b135c9AA67f0D8e9c6 +MastercopyDemurrageERC20: 0xB3B6950411bE5b9411CdE616B669204A24569bD5 +MastercopyInflationaryERC20: 0xB04Ad230CBD53Faf0888de2e131467BD933F8237 +MastercopyStandardVault: 0xb2bEcDfEB4afcaB94Fa05b3822D35cD401C7897A diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_BaseGroupMintPolicy.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_BaseGroupMintPolicy.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_BaseGroupMintPolicy.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_ERC20Lift.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_ERC20Lift.txt new file mode 100644 index 0000000..a69b8c8 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_ERC20Lift.txt @@ -0,0 +1 @@ +0xEddc960D3c78692BF38577054cb0a35114AE35e0 0x5525cbF9ad01a4E805ed1b40723D6377b336eCcf 0xB3B6950411bE5b9411CdE616B669204A24569bD5 0xB04Ad230CBD53Faf0888de2e131467BD933F8237 diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_Hub.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_Hub.txt new file mode 100644 index 0000000..c0d8b4c --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_Hub.txt @@ -0,0 +1 @@ +0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0x5525cbF9ad01a4E805ed1b40723D6377b336eCcf 0x8C9BeAccb6b7DBd3AeffB5D77cab36b62Fe98882 0xd6407bc654a4de9b044b84dCfF9B77F0250fCba3 0x66A024F2055fa84b40f27c2f3Eb68A848276A641 1675209600 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyDemurrageERC20.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyDemurrageERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyDemurrageERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyInflationaryERC20.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyInflationaryERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyInflationaryERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyStandardVault.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyStandardVault.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_MastercopyStandardVault.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_Migration.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_Migration.txt new file mode 100644 index 0000000..73ca5c5 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_Migration.txt @@ -0,0 +1 @@ +0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0xEddc960D3c78692BF38577054cb0a35114AE35e0 1675209600 diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_NameRegistry.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_NameRegistry.txt new file mode 100644 index 0000000..df899d5 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_NameRegistry.txt @@ -0,0 +1 @@ +0xEddc960D3c78692BF38577054cb0a35114AE35e0 diff --git a/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_StandardTreasury.txt b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_StandardTreasury.txt new file mode 100644 index 0000000..755b4be --- /dev/null +++ b/script/deployments/chiado-rc-0.3.5-alpha-1d343b7-240808-183621/constructorArgs_StandardTreasury.txt @@ -0,0 +1 @@ +0xEddc960D3c78692BF38577054cb0a35114AE35e0 0xb2bEcDfEB4afcaB94Fa05b3822D35cD401C7897A diff --git a/script/deployments/chiadoDeploy.sh b/script/deployments/chiadoDeploy.sh index 94a631c..f33e1f2 100755 --- a/script/deployments/chiadoDeploy.sh +++ b/script/deployments/chiadoDeploy.sh @@ -77,7 +77,7 @@ INFLATION_DAY_ZERO=1675209600 # put a long bootstrap time for testing bootstrap BOOTSTRAP_ONE_YEAR=31540000 # fallback URI -URI='https://fallback.aboutcircles.com/v1/circles/{id}.json' +URI='https://gateway.aboutcircles.com/v1/circles/{id}.json' # re-export the variables for use here and in the general calculation JS script export PRIVATE_KEY=$PRIVATE_KEY_CHIADO diff --git a/script/deployments/gnosisChainDeploy.sh b/script/deployments/gnosisChainDeploy.sh index 28a622e..c34f8e3 100755 --- a/script/deployments/gnosisChainDeploy.sh +++ b/script/deployments/gnosisChainDeploy.sh @@ -99,7 +99,7 @@ INFLATION_DAY_ZERO=1602720000 # put a long bootstrap time for testing bootstrap to one year BOOTSTRAP_ONE_YEAR=31540000 # fallback URI -URI='https://fallback.aboutcircles.com/v1/circles/{id}.json' +URI='https://gateway.aboutcircles.com/v1/circles/{id}.json' # re-export the variables for use here and in the general calculation JS script export PRIVATE_KEY=$PRIVATE_KEY_GNOSIS diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_BaseGroupMintPolicy.txt b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_BaseGroupMintPolicy.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_BaseGroupMintPolicy.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_ERC20Lift.txt b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_ERC20Lift.txt new file mode 100644 index 0000000..79545ae --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_ERC20Lift.txt @@ -0,0 +1 @@ +0x7bC1F123089Bc1f384b6379d0587968d1CD5830a 0xb95eF3f3E693531d9588815bcA954dC8dce30937 0x3148182009D825aBfABfaeb11fc8F2e8a25dAc92 0x1b2fe34fCF2956A316936bC3F4E963fdaf9c1c72 diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_Hub.txt b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_Hub.txt new file mode 100644 index 0000000..6df2075 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_Hub.txt @@ -0,0 +1 @@ +0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0xb95eF3f3E693531d9588815bcA954dC8dce30937 0xEaBa6046103C3A2f5A681fD4323f78C647Fb4292 0xBB62B89fd96f42fe60216DCA3afefC67c95486d7 0x2434151eB40Af648AbcF73a6C9F1711FfF0F498B 1602720000 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyDemurrageERC20.txt b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyDemurrageERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyDemurrageERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyInflationaryERC20.txt b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyInflationaryERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyInflationaryERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyStandardVault.txt b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyStandardVault.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_MastercopyStandardVault.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_Migration.txt b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_Migration.txt new file mode 100644 index 0000000..34b070a --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_Migration.txt @@ -0,0 +1 @@ +0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0x7bC1F123089Bc1f384b6379d0587968d1CD5830a 1602720000 diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_NameRegistry.txt b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_NameRegistry.txt new file mode 100644 index 0000000..f6c1e74 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_NameRegistry.txt @@ -0,0 +1 @@ +0x7bC1F123089Bc1f384b6379d0587968d1CD5830a diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_StandardTreasury.txt b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_StandardTreasury.txt new file mode 100644 index 0000000..a3db43f --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/constructorArgs_StandardTreasury.txt @@ -0,0 +1 @@ +0x7bC1F123089Bc1f384b6379d0587968d1CD5830a 0x120DaC440c97d2D279988f056CCEf839B7E30409 diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/gnosischain-artefacts-rc-0.3.5-alpha-1d343b7-240808-185913.txt b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/gnosischain-artefacts-rc-0.3.5-alpha-1d343b7-240808-185913.txt new file mode 100644 index 0000000..cd1c49a --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/gnosischain-artefacts-rc-0.3.5-alpha-1d343b7-240808-185913.txt @@ -0,0 +1,9 @@ +{"contractName":"Hub","deployedAddress":"0x7bC1F123089Bc1f384b6379d0587968d1CD5830a","sourcePath":"src/hub/Hub.sol:Hub","constructor-args":"0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0xb95eF3f3E693531d9588815bcA954dC8dce30937 0xEaBa6046103C3A2f5A681fD4323f78C647Fb4292 0xBB62B89fd96f42fe60216DCA3afefC67c95486d7 0x2434151eB40Af648AbcF73a6C9F1711FfF0F498B 1602720000 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json","argumentsFile":"constructorArgs_Hub.txt"} +{"contractName":"Migration","deployedAddress":"0xEaBa6046103C3A2f5A681fD4323f78C647Fb4292","sourcePath":"src/migration/Migration.sol:Migration","constructor-args":"0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0x7bC1F123089Bc1f384b6379d0587968d1CD5830a 1602720000","argumentsFile":"constructorArgs_Migration.txt"} +{"contractName":"NameRegistry","deployedAddress":"0xb95eF3f3E693531d9588815bcA954dC8dce30937","sourcePath":"src/names/NameRegistry.sol:NameRegistry","constructor-args":"0x7bC1F123089Bc1f384b6379d0587968d1CD5830a","argumentsFile":"constructorArgs_NameRegistry.txt"} +{"contractName":"ERC20Lift","deployedAddress":"0xBB62B89fd96f42fe60216DCA3afefC67c95486d7","sourcePath":"src/lift/ERC20Lift.sol:ERC20Lift","constructor-args":"0x7bC1F123089Bc1f384b6379d0587968d1CD5830a 0xb95eF3f3E693531d9588815bcA954dC8dce30937 0x3148182009D825aBfABfaeb11fc8F2e8a25dAc92 0x1b2fe34fCF2956A316936bC3F4E963fdaf9c1c72","argumentsFile":"constructorArgs_ERC20Lift.txt"} +{"contractName":"StandardTreasury","deployedAddress":"0x2434151eB40Af648AbcF73a6C9F1711FfF0F498B","sourcePath":"src/treasury/StandardTreasury.sol:StandardTreasury","constructor-args":"0x7bC1F123089Bc1f384b6379d0587968d1CD5830a 0x120DaC440c97d2D279988f056CCEf839B7E30409","argumentsFile":"constructorArgs_StandardTreasury.txt"} +{"contractName":"BaseGroupMintPolicy","deployedAddress":"0x2470B43fc3303fCa660E68c86e3bEb8CE353C556","sourcePath":"src/groups/BaseMintPolicy.sol:MintPolicy","constructor-args":"","argumentsFile":"constructorArgs_BaseGroupMintPolicy.txt"} +{"contractName":"MastercopyDemurrageERC20","deployedAddress":"0x3148182009D825aBfABfaeb11fc8F2e8a25dAc92","sourcePath":"src/lift/DemurrageCircles.sol:DemurrageCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyDemurrageERC20.txt"} +{"contractName":"MastercopyInflationaryERC20","deployedAddress":"0x1b2fe34fCF2956A316936bC3F4E963fdaf9c1c72","sourcePath":"src/lift/InflationaryCircles.sol:InflationaryCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyInflationaryERC20.txt"} +{"contractName":"MastercopyStandardVault","deployedAddress":"0x120DaC440c97d2D279988f056CCEf839B7E30409","sourcePath":"src/treasury/StandardVault.sol:StandardVault","constructor-args":"","argumentsFile":"constructorArgs_MastercopyStandardVault.txt"} diff --git a/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913.log b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913.log new file mode 100644 index 0000000..1167513 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913/gnosischain-rc-0.3.5-alpha-1d343b7-240808-185913.log @@ -0,0 +1,18 @@ +Gnosis Chain deployment +================= +Deployment Date: 2024-08-08 18:59:13 +Version: rc-0.3.5-alpha +Git Commit: 1d343b7fa8501c0347568df9318414f630cd585d +Deployer Address: 0x7619F26728Ced663E50E578EB6ff42430931564c, Initial nonce: 47 +Compiler Version: v0.8.23+commit.f704f362 + +Deployed Contracts: +Hub: 0x7bC1F123089Bc1f384b6379d0587968d1CD5830a +Migration: 0xEaBa6046103C3A2f5A681fD4323f78C647Fb4292 +NameRegistry: 0xb95eF3f3E693531d9588815bcA954dC8dce30937 +ERC20Lift: 0xBB62B89fd96f42fe60216DCA3afefC67c95486d7 +StandardTreasury: 0x2434151eB40Af648AbcF73a6C9F1711FfF0F498B +BaseGroupMintPolicy: 0x2470B43fc3303fCa660E68c86e3bEb8CE353C556 +MastercopyDemurrageERC20: 0x3148182009D825aBfABfaeb11fc8F2e8a25dAc92 +MastercopyInflationaryERC20: 0x1b2fe34fCF2956A316936bC3F4E963fdaf9c1c72 +MastercopyStandardVault: 0x120DaC440c97d2D279988f056CCEf839B7E30409