From 788ad4d44e40fc745a0589906a5cc9ea25dd9ca7 Mon Sep 17 00:00:00 2001 From: TtheBC01 Date: Wed, 24 May 2023 23:48:14 -0700 Subject: [PATCH 1/6] new getter and listing functions --- .../contracts/contracts/consent/Consent.sol | 90 ++++++++++++++++++- .../contracts/consent/ConsentFactory.sol | 4 +- .../contracts/contracts/consent/IConsent.sol | 24 ++++- .../contracts/consent/IConsentFactory.sol | 4 +- packages/contracts/tasks/consent.js | 6 +- 5 files changed, 120 insertions(+), 8 deletions(-) diff --git a/packages/contracts/contracts/consent/Consent.sol b/packages/contracts/contracts/consent/Consent.sol index b948dd31ed..f6d5fa3a4d 100644 --- a/packages/contracts/contracts/consent/Consent.sol +++ b/packages/contracts/contracts/consent/Consent.sol @@ -67,6 +67,15 @@ contract Consent is /// @dev the maximum number of consent tokens that can be issued uint public maxCapacity; + /// @dev updateable name for the consent registry used in data wallet UI + string private registryName; + + /// @dev updatable description for the consent registry used in data wallet UI + string private registryDesc; + + /// @dev updateable image URL for this consent registry used in data wallet UI + string private registryImg; + /* MODIFIERS */ /// Checks if open opt in is current disabled @@ -123,6 +132,40 @@ contract Consent is /* CORE FUNCTIONS */ + /// @notice Get all details for a consent registry in one rpc call + function getRegistryDetails() external view returns(RegistryDetails memory) { + RegistryDetails memory deets = RegistryDetails( + registryName, + registryDesc, + registryImg, + baseURI, + maxCapacity, + totalSupply, + openOptInDisabled, + queryHorizon, + domains, + tags + ); + return deets; + } + + /// @notice Adds a new tag to the global namespace and stakes it for this consent contract + /// @dev passing an empty string will leave the attribute unchanged after the transaction completes + /// @param _name Human readable string used as the display name for the rewards marketplace + /// @param _desc Human readable description used in the rewards marketplace for user context + /// @param _img URL pointing to thumbnail image for use in rewards marketplace UI + function updateConsentRegistryDetails(string calldata _name, string calldata _desc, string calldata _img) external { + if (bytes(_name).length > 0) { + registryName = _name; + } + if (bytes(_desc).length > 0) { + registryDesc = _desc; + } + if (bytes(_img).length > 0) { + registryImg = _img; + } + } + /// @notice Get the number of tags staked by this contract function getNumberOfStakedTags() external view returns (uint256) { return tags.length; @@ -215,7 +258,50 @@ contract Consent is consentFactoryInstance.insertDownstream(tag, _existingSlot, _newSlot); } - /// @notice Replaces an existing listing that has expired (works for head and tail listings) + /// @notice Move an existing listing from its current slot to upstream of a new existing slot + /// @dev This function assumes that tag is not the only member in the global list (i.e. getTagTotal(tag) > 1) + /// @dev This function also assumes that the listing is not expired + /// @param tag Human readable string denoting the target tag to stake + /// @param _newSlot The new slot to move the listing to + /// @param _existingSlot The neighboring listing to _newSlow + function moveExistingListingUpstream( + string memory tag, + uint256 _newSlot, + uint256 _existingSlot + ) external onlyRole(STAKER_ROLE) { + // check + require( + tagIndices[tag] > 0, + "Consent Contract: This tag has not been staked" + ); + + // effects + uint256 removalSlot = tags[tagIndices[tag] - 1].slot; + tags[tagIndices[tag] - 1].slot = _newSlot; + + // interaction + // remove from current slot, reverts if the listing was replaced after expiration + consentFactoryInstance.removeListing(tag, removalSlot); + // add to the new slot, reverts if _existingSlot has no current listing + consentFactoryInstance.insertUpstream(tag, _newSlot, _existingSlot); + } + + /// @notice Restakes a listing from this registry that has expired (works for head and tail listings) + /// @param tag Human readable string denoting the target tag to stake + function restakeExpiredListing( + string memory tag + ) external onlyRole(STAKER_ROLE) { + // check + require( + tagIndices[tag] > 0, + "Consent Contract: This tag has not been staked" + ); + + // interaction + consentFactoryInstance.replaceExpiredListing(tag, tags[tagIndices[tag] - 1].slot); + } + + /// @notice Replaces an existing listing from another registry that has expired (works for head and tail listings) /// @param tag Human readable string denoting the target tag to stake /// @param _slot The expired slot to replace with a new listing function replaceExpiredListing( @@ -297,7 +383,7 @@ contract Consent is _updateCounterAndTokenFlags(tokenId, agreementFlags); - /// increase total supply count, this is 20,0000 gas + /// increase total supply count, this is 20,000 gas totalSupply++; } diff --git a/packages/contracts/contracts/consent/ConsentFactory.sol b/packages/contracts/contracts/consent/ConsentFactory.sol index 70e7e1e8e5..c89493c0d7 100644 --- a/packages/contracts/contracts/consent/ConsentFactory.sol +++ b/packages/contracts/contracts/consent/ConsentFactory.sol @@ -137,8 +137,8 @@ contract ConsentFactory is Initializable, PausableUpgradeable, AccessControlEnum require(_newSlot > 0, "ConsentFactory: _newSlot must be greater than 0"); require(_newSlot > _existingSlot, "ConsentFactory: _newSlot must be greater than _existingSlot"); - // The new listing must fit between _upstream and its current downstresam - // if the next variable is 0, it means the slot is uninitialized and thus it is invalid _upstream entry + // The new listing must fit between _upstream and its current downstream + // if the previous variable is 0, it means the slot is uninitialized and thus it is invalid _upstream entry bytes32 LLKey = keccak256(abi.encodePacked(tag)); Listing memory existingListing = listings[LLKey][_existingSlot]; require(existingListing.previous > _newSlot, "ConsentFactory: _newSlot is greater than existingListing.previous"); diff --git a/packages/contracts/contracts/consent/IConsent.sol b/packages/contracts/contracts/consent/IConsent.sol index bb8e6ac43f..261e42e9e2 100644 --- a/packages/contracts/contracts/consent/IConsent.sol +++ b/packages/contracts/contracts/consent/IConsent.sol @@ -11,10 +11,24 @@ interface IConsent { address staker; // address which staked the specific tag } + // helper struct to retrieve nearly all registry details in one http request + struct RegistryDetails{ + string name; + string desc; + string imgURL; + string baseURI; + uint maxCapacity; + uint totalSupply; + bool openOptInDisabled; + uint queryHorizon; + string[] domains; + Tag[] tags; + } + /* EVENTS */ /// @notice Emitted when a request for data is made - /// @dev The SDQL services listens for this event + /// @dev The data wallet client subscribes to this event /// @param requester Indexed address of data requester /// @param ipfsCIDIndexed The indexed IPFS CID pointing to an SDQL instruction /// @param ipfsCID The IPFS CID pointing to an SDQL instruction @@ -34,6 +48,10 @@ interface IConsent { /* External Functions */ + function getRegistryDetails() external view returns(RegistryDetails memory); + + function updateConsentRegistryDetails(string calldata _name, string calldata _desc, string calldata _img) external; + function tagIndices(string calldata) external view returns(uint256); function baseURI() external view returns(string memory); @@ -60,6 +78,10 @@ interface IConsent { function newLocalTagDownstream(string memory tag, uint256 _existingSlot, uint256 _newSlot) external; + function moveExistingListingUpstream(string memory tag, uint256 _newSlot, uint256 _existingSlot) external; + + function restakeExpiredListing(string memory tag) external; + function replaceExpiredListing(string memory tag, uint256 _slot) external; function removeListing(string memory tag) external returns (string memory); diff --git a/packages/contracts/contracts/consent/IConsentFactory.sol b/packages/contracts/contracts/consent/IConsentFactory.sol index 967d37ef90..c4e7582a05 100644 --- a/packages/contracts/contracts/consent/IConsentFactory.sol +++ b/packages/contracts/contracts/consent/IConsentFactory.sol @@ -5,8 +5,8 @@ interface IConsentFactory { /// @dev Listing object for storing marketplace listings struct Listing{ - uint256 previous; // pointer to the previous active slot - uint256 next; // pointer to the next active slot + uint256 previous; // pointer to the higher value active slot + uint256 next; // pointer to the next lower value active slot address consentContract; // address of the target consent contract uint256 timeExpiring; // unix timestamp when the listing expires and can be replaced } diff --git a/packages/contracts/tasks/consent.js b/packages/contracts/tasks/consent.js index cfe46fdb90..a7599effd4 100644 --- a/packages/contracts/tasks/consent.js +++ b/packages/contracts/tasks/consent.js @@ -98,10 +98,14 @@ task( "getMarketplaceListings", "Get CIDs containing marketplace listing content", ) + .addParam("category", "Which category to inspect") + .addParam("startingslot", "Which slot to start from") .addParam("howmany", "how many listings to return") .setAction(async (taskArgs) => { const howmany = taskArgs.howmany; const provider = await hre.ethers.provider; + const startingSlot = taskArgs.startingSlot; + const tag = taskArgs.category; // attach the first signer account to the consent contract handle const consentContractFactorHandle = new hre.ethers.Contract( @@ -113,7 +117,7 @@ task( await consentContractFactorHandle .listingsHead() .then((listingsHead) => { - return consentContractFactorHandle.getListings(listingsHead, howmany); + return consentContractFactorHandle.getListingsForward(tag, startingSlot, howmany, true); }) .then((output) => { console.log("CIDs", output[0]); From 103fa6802d25c7f523d70131704d639e6bca6007 Mon Sep 17 00:00:00 2001 From: TtheBC01 Date: Thu, 25 May 2023 15:37:47 -0700 Subject: [PATCH 2/6] added unit tests for new staking functions --- packages/contracts/test/consentFactory.js | 45 ++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/contracts/test/consentFactory.js b/packages/contracts/test/consentFactory.js index 65498503b2..111fc187a4 100644 --- a/packages/contracts/test/consentFactory.js +++ b/packages/contracts/test/consentFactory.js @@ -56,6 +56,7 @@ describe("ConsentFactory", () => { describe("Stake-for-Ranking", function () { it("Test basic Marketplace insertion and deletion", async function () { // SCENARIO: User 1 initializes slot 3 => User 2 inserts upstream slot 4 => User 1 removes listing (which removes their slot 3) => User 1 inserts downstream of User 2 on slot 2 + // => User 1 moves from slot 2 to slot 10 // create a couple of consent contracts await consentFactory @@ -98,6 +99,7 @@ describe("ConsentFactory", () => { const slot2 = 2; const slot3 = 3; const slot4 = 4; + const slot10= 10; const tag2 = "short-string-2"; const tag3 = "short-string-3"; @@ -155,7 +157,7 @@ describe("ConsentFactory", () => { const forwardList = await consentFactory.getListingsForward( tag2, 4, - 4, + 2, true, ); @@ -175,6 +177,27 @@ describe("ConsentFactory", () => { await expect(backwardList[0][1]).to.eq("Listing2"); await expect(backwardList[1][0].previous).to.eq(slot4); await expect(backwardList[1][1].next).to.eq(slot2); + + // user 1 moves their listing upstream of user 2 + await deployedConsentInstance1 + .connect(user1) + .moveExistingListingUpstream(tag2, slot10, slot4) + .then((txrct) => { + return txrct.wait(); + }); + + const forwardList2 = await consentFactory.getListingsForward( + tag2, + 10, + 2, + true, + ); + + // check that the new ordering makes sense + await expect(forwardList2[0][0]).to.eq("Listing1"); + await expect(forwardList2[0][1]).to.eq("Listing2"); + await expect(forwardList2[1][0].next).to.eq(slot4); + await expect(forwardList2[1][1].previous).to.eq(slot10); }); it("Insert upstream and test listing getters", async function () { @@ -472,6 +495,26 @@ describe("ConsentFactory", () => { }); expect(await consentFactory.getTagTotal(tag2)).to.eq(1); + + // restaking won't work if you are still active + await expect( + deployedConsentInstance2 + .connect(user2) + .restakeExpiredListing(tag2), + ).to.revertedWith("ConsentFactory: current listing is still active"); + + // fastforward and restake expired listing + await ethers.provider.send("evm_increaseTime", [ + listingDuration.toNumber(), + ]); + await ethers.provider.send("evm_mine"); + + await deployedConsentInstance2 + .connect(user2) + .restakeExpiredListing(tag2) + .then((txrct) => { + return txrct.wait(); + }); }); it("Test admin can remove listings", async function () { From 0a19f2026825ca76c9a83b38a11b1e4a731ce90d Mon Sep 17 00:00:00 2001 From: TtheBC01 Date: Mon, 24 Jul 2023 08:59:27 -0700 Subject: [PATCH 3/6] save work --- .../contracts/contracts/consent/Consent.sol | 24 +++++++++++++++++-- .../contracts/contracts/consent/IConsent.sol | 1 + .../contracts/scripts/consent-stack-only.js | 4 ++-- packages/contracts/test/consentFactory.js | 14 +++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/packages/contracts/contracts/consent/Consent.sol b/packages/contracts/contracts/consent/Consent.sol index f6d5fa3a4d..7b7fed013f 100644 --- a/packages/contracts/contracts/consent/Consent.sol +++ b/packages/contracts/contracts/consent/Consent.sol @@ -76,6 +76,9 @@ contract Consent is /// @dev updateable image URL for this consent registry used in data wallet UI string private registryImg; + /// @dev Mapping owner address to a token id + mapping(address => uint256) private ownership; + /* MODIFIERS */ /// Checks if open opt in is current disabled @@ -133,7 +136,11 @@ contract Consent is /* CORE FUNCTIONS */ /// @notice Get all details for a consent registry in one rpc call - function getRegistryDetails() external view returns(RegistryDetails memory) { + /// @dev also takes an address as an input so the data wallet can determin membership info + /// @param audienceMember address of the consent key used by the calling data wallet client. + function getRegistryDetails(address audienceMember) external view returns(RegistryDetails memory) { + // if memberTokenId is 0, then the address is not an audience member + address memberTokenId = ownership(audienceMember); RegistryDetails memory deets = RegistryDetails( registryName, registryDesc, @@ -144,7 +151,8 @@ contract Consent is openOptInDisabled, queryHorizon, domains, - tags + tags, + memberTokenId ); return deets; } @@ -385,6 +393,9 @@ contract Consent is /// increase total supply count, this is 20,000 gas totalSupply++; + + /// create reverse mapping + ownership[_msgSender()] = tokenId; } /// @notice Allows specific users to opt in to sharing their data @@ -424,6 +435,9 @@ contract Consent is /// increase total supply count totalSupply++; + + /// create reverse mapping + ownership[_msgSender()] = tokenId; } /// @notice Allows Signature Issuer to send anonymous invitation link to end user to opt in @@ -463,6 +477,9 @@ contract Consent is /// increase total supply count before interaction totalSupply++; + + /// create reverse mapping + ownership[_msgSender()] = tokenId; } /// @notice Allows users to opt out of sharing their data @@ -753,6 +770,9 @@ contract Consent is /// decrease total supply count totalSupply--; + /// create reverse mapping + delete ownership[_msgSender()]; + _updateCounterAndTokenFlags(tokenId, agreementFlagsArray[tokenId]); super._burn(tokenId); diff --git a/packages/contracts/contracts/consent/IConsent.sol b/packages/contracts/contracts/consent/IConsent.sol index 261e42e9e2..1b1b4ea84f 100644 --- a/packages/contracts/contracts/consent/IConsent.sol +++ b/packages/contracts/contracts/consent/IConsent.sol @@ -23,6 +23,7 @@ interface IConsent { uint queryHorizon; string[] domains; Tag[] tags; + uint256 tokenId; } /* EVENTS */ diff --git a/packages/contracts/scripts/consent-stack-only.js b/packages/contracts/scripts/consent-stack-only.js index 892c97022c..0837dc5dbf 100644 --- a/packages/contracts/scripts/consent-stack-only.js +++ b/packages/contracts/scripts/consent-stack-only.js @@ -6,7 +6,7 @@ const { ethers, upgrades } = require("hardhat"); // declare variables that need to be referenced by other functions -let trustedForwarderAddress; +let trustedForwarderAddress = "0xdB5c885944d903Ac5c146eef400D2ee20572d357"; let consentAddress; async function deployMinimalForwarder() { @@ -57,7 +57,7 @@ async function deployConsentFactory() { // function that runs the full deployment of all contracts async function fullDeployment() { - await deployMinimalForwarder(); + //await deployMinimalForwarder(); await deployConsent(); await deployConsentFactory(); diff --git a/packages/contracts/test/consentFactory.js b/packages/contracts/test/consentFactory.js index 111fc187a4..5f0dd3ba91 100644 --- a/packages/contracts/test/consentFactory.js +++ b/packages/contracts/test/consentFactory.js @@ -465,6 +465,20 @@ describe("ConsentFactory", () => { return txrct.wait(); }); + await deployedConsentInstance1 + .connect(user1) + .removeListing(tag2) + .then((txrct) => { + return txrct.wait(); + }); + + await deployedConsentInstance1 + .connect(user1) + .newGlobalTag(tag2, slot3) + .then((txrct) => { + return txrct.wait(); + }); + await expect( deployedConsentInstance2 .connect(user2) From 75e86c755415651022d8a140597bd945c245cb5c Mon Sep 17 00:00:00 2001 From: TtheBC01 Date: Tue, 5 Sep 2023 10:49:39 -0700 Subject: [PATCH 4/6] removed depricated contracts --- .../contracts/contracts/consent/Consent.sol | 170 ++++++++------- .../contracts/contracts/consent/IConsent.sol | 6 +- .../metatx/SynamintForwarderUpgradeable.sol | 20 -- .../contracts/contracts/registry/Crumbs.sol | 199 ------------------ .../contracts/contracts/registry/README.md | 8 - .../contracts/contracts/registry/Sift.sol | 154 -------------- .../contracts/contracts/token/DoodleToken.sol | 4 +- 7 files changed, 85 insertions(+), 476 deletions(-) delete mode 100644 packages/contracts/contracts/metatx/SynamintForwarderUpgradeable.sol delete mode 100644 packages/contracts/contracts/registry/Crumbs.sol delete mode 100644 packages/contracts/contracts/registry/README.md delete mode 100644 packages/contracts/contracts/registry/Sift.sol diff --git a/packages/contracts/contracts/consent/Consent.sol b/packages/contracts/contracts/consent/Consent.sol index b948dd31ed..7c44dd9b7f 100644 --- a/packages/contracts/contracts/consent/Consent.sol +++ b/packages/contracts/contracts/consent/Consent.sol @@ -52,10 +52,7 @@ contract Consent is /// @dev Flag of whether open opt in is disabled or not bool public openOptInDisabled; - /// @dev Trusted forwarder address for meta-transactions - address public trustedForwarder; - - /// @dev Array of trusted domains + /// @dev Array of trusted domains for prompting user optins string[] domains; /// @dev Oldest block that should be scanned for requestForData events @@ -69,7 +66,7 @@ contract Consent is /* MODIFIERS */ - /// Checks if open opt in is current disabled + /// Checks if open opt in is current disabled (i.e. invite-only opt ins) modifier whenNotDisabled() { require( !openOptInDisabled, @@ -80,16 +77,18 @@ contract Consent is /// @notice Initializes the contract /// @dev Uses the initializer modifier to to ensure the contract is only initialized once - /// @param _trustedForwarder Address of EIP2771-compatible meta-tx forwarding contract /// @param _consentOwner Address of the owner of this contract /// @param baseURI_ The base uri /// @param _name Name of the Consent Contract + /// @param _domains array of trusted domain URIs/URLs for triggering optin prompts + /// @param _maxCapacity integer used for maximuim number of allowed optins /// @param _contractFactoryAddress address of the originating consent factory function initialize( - address _trustedForwarder, address _consentOwner, string memory baseURI_, string memory _name, + string[] memory _domains, + uint256 _maxCapacity, address _contractFactoryAddress ) public initializer { __ERC721_init(_name, "CONSENT"); @@ -101,18 +100,20 @@ contract Consent is consentFactoryInstance = IConsentFactory(_contractFactoryAddress); maxTags = consentFactoryInstance.maxTagsPerListing(); // it's assumed maxTags will only be increased in the future - // set trusted forwarder for meta-txs - trustedForwarder = _trustedForwarder; - // set the queryHorizon to be the current block number; queryHorizon = block.number; // set the initial maximum capacity (we set to a relatively large number) - maxCapacity = 100000; + maxCapacity = _maxCapacity; - // set the base uri so the consent contract has content to display in the marketplace + // set the base uri so the consent contract has content to display to users during optin flow baseURI = baseURI_; + // set trusted domain array + for (uint256 i; i < _domains.length; ) { + domains.push(_domains[i]); + } + // use user to bypass the call back to the ConsentFactory to update the user's roles array mapping super._grantRole(DEFAULT_ADMIN_ROLE, _consentOwner); super._grantRole(PAUSER_ROLE, _consentOwner); @@ -276,64 +277,75 @@ contract Consent is } /// @notice Allows any user to opt in to sharing their data - /// @dev Mints user a Consent token + /// @dev Mints a consent token to an EOA (the EOA should idealy have no tx-history, but this is not enforced) /// @param tokenId User's Consent token id to mint against /// @param agreementFlags A bytes32 array of the user's consent token flag indicating their data permissioning settings + /// @param identityCommitment A bytes32 array of the user's identity commitment used in generating zk proof of consent + /// @param stealthSignature ECDSA signature from user's stealth address (no tx history), the stealth address will own the consent token function optIn( uint256 tokenId, - bytes32 agreementFlags + bytes32 agreementFlags, + bytes32 identityCommitment, + bytes memory stealthSignature ) external whenNotPaused whenNotDisabled { - /// if user has opted in before, revert - require( - balanceOf(_msgSender()) == 0, - "Consent: User has already opted in" + + bytes32 optinHash = ECDSAUpgradeable.toEthSignedMessageHash( + keccak256(abi.encodePacked(address(this), tokenId, agreementFlags, identityCommitment)) ); + /// calculate the recipient address, if user has opted in before, revert + address recipient = _isValidOptInSignature(optinHash, stealthSignature); + /// if consent cohort is at capacity, revert require(!_atCapacity(), "Consent: cohort is at capacity"); /// mint the consent token and set its agreement uri - _safeMint(_msgSender(), tokenId); + _safeMint(recipient, tokenId); _updateCounterAndTokenFlags(tokenId, agreementFlags); - /// increase total supply count, this is 20,0000 gas + /// increase total supply count, this is 20,000 gas totalSupply++; } /// @notice Allows specific users to opt in to sharing their data - /// @dev For restricted opt ins, the owner will first sign a digital signature on-chain - /// @dev The function is called with the signature from SIGNER_ROLE + /// @dev Mints a consent token to an EOA (the EOA should idealy have no tx-history, but this is not enforced) + /// @dev The function must be called with the signature from SIGNER_ROLE /// @dev If the message signature is valid, the user calling this function is minted a Consent token /// @param tokenId User's Consent token id to mint against (also serves as a nonce) /// @param agreementFlags A bytes32 array of the user's consent token flag indicating their data permissioning settings (this param is not included in the sig hash) - /// @param signature Signature to be recovered from the hash of the target contract address, target recipient address, and token id to be redeemeed + /// @param identityCommitment A bytes32 array of the user's identity commitment used in generating zk proof of consent + /// @param stealthSignature ECDSA signature from user's stealth address (no tx history), the stealth address will own the consent token + /// @param inviteSignature Signature to be recovered from the hash of the target contract address, target recipient address, and token id to be redeemeed function restrictedOptIn( uint256 tokenId, bytes32 agreementFlags, - bytes memory signature + bytes32 identityCommitment, + bytes memory stealthSignature, + bytes memory inviteSignature ) external whenNotPaused { - /// if user has opted in before, revert - require( - balanceOf(_msgSender()) == 0, - "Consent: User has already opted in" + bytes32 optinHash = ECDSAUpgradeable.toEthSignedMessageHash( + keccak256(abi.encodePacked(address(this), tokenId, agreementFlags, identityCommitment)) ); + /// calculate the recipient address, if user has opted in before, revert + address recipient = _isValidOptInSignature(optinHash, stealthSignature); + /// if consent cohort is at capacity, revert require(!_atCapacity(), "Consent: cohort is at capacity"); - bytes32 hash = ECDSAUpgradeable.toEthSignedMessageHash( + bytes32 inviteHash = ECDSAUpgradeable.toEthSignedMessageHash( keccak256(abi.encodePacked(address(this), _msgSender(), tokenId)) ); /// check the signature against the payload require( - _isValidSignature(hash, signature), + _isValidSignerSignature(inviteHash, inviteSignature), "Consent: Contract owner did not sign this message" ); /// mint the consent token and set its uri - _safeMint(_msgSender(), tokenId); + _safeMint(recipient, tokenId); _updateCounterAndTokenFlags(tokenId, agreementFlags); /// increase total supply count @@ -341,38 +353,44 @@ contract Consent is } /// @notice Allows Signature Issuer to send anonymous invitation link to end user to opt in - /// @dev For restricted opt ins, the owner will first sign a digital signature on-chain - /// @dev The function is called with the a signature from SIGNER_ROLE + /// @dev Mints a consent token to an EOA (the EOA should idealy have no tx-history, but this is not enforced) + /// @dev The function must be called with the signature from SIGNER_ROLE /// @dev If the message signature is valid, the user calling this function is minted a Consent token /// @param tokenId User's Consent token id to mint against (also serves as a nonce) /// @param agreementFlags A bytes32 array of the user's consent token flag indicating their data permissioning settings (this param is not included in the sig hash) - /// @param signature Signature to be recovered from the hash of the target contract address and token id to be redeemeed + /// @param identityCommitment A bytes32 array of the user's identity commitment used in generating zk proof of consent + /// @param stealthSignature ECDSA signature from user's stealth address (no tx history), the stealth address will own the consent token + /// @param inviteSignature Signature to be recovered from the hash of the target contract address, target recipient address, and token id to be redeemeed function anonymousRestrictedOptIn( uint256 tokenId, bytes32 agreementFlags, - bytes memory signature + bytes32 identityCommitment, + bytes memory stealthSignature, + bytes memory inviteSignature ) external whenNotPaused { - /// if user has opted in before, revert - require( - balanceOf(_msgSender()) == 0, - "Consent: User has already opted in" + bytes32 optinHash = ECDSAUpgradeable.toEthSignedMessageHash( + keccak256(abi.encodePacked(address(this), tokenId, agreementFlags, identityCommitment)) ); + /// calculate the recipient address, if user has opted in before, revert + address recipient = _isValidOptInSignature(optinHash, stealthSignature); + /// if consent cohort is at capacity, revert require(!_atCapacity(), "Consent: cohort is at capacity"); bytes32 hash = ECDSAUpgradeable.toEthSignedMessageHash( keccak256(abi.encodePacked(address(this), tokenId)) ); + /// check the signature against the payload /// Any account possessing the signature and payload can call this method require( - _isValidSignature(hash, signature), + _isValidSignerSignature(hash, inviteSignature), "Consent: Contract owner did not sign this message" ); /// mint the consent token and set its uri - _safeMint(_msgSender(), tokenId); + _safeMint(recipient, tokenId); _updateCounterAndTokenFlags(tokenId, agreementFlags); /// increase total supply count before interaction @@ -444,11 +462,6 @@ contract Consent is queryHorizon = queryHorizon_; } - /// @notice update the trusted forwarder address based on factory settings - function updateTrustedForwarder() external onlyRole(DEFAULT_ADMIN_ROLE) { - trustedForwarder = consentFactoryInstance.trustedForwarder(); - } - /// @notice Admin endpoint to change the maximum number of tags a consent contract can stake against function updateMaxTagsLimit() external onlyRole(DEFAULT_ADMIN_ROLE) { maxTags = consentFactoryInstance.maxTagsPerListing(); @@ -542,15 +555,6 @@ contract Consent is /* GETTER */ - /// @dev Inherited from ERC2771ContextUpgradeable to embed its features directly in this contract - /// @dev This is a workaround as ERC2771ContextUpgradeable does not have an _init() function - /// @dev Allows the factory to deploy a BeaconProxy that initiates a Consent contract without a constructor - function isTrustedForwarder( - address forwarder - ) public view virtual returns (bool) { - return forwarder == trustedForwarder; - } - /// @notice Convenient function for asking contract if there is room left in the campaign in one function call function _atCapacity() internal view virtual returns (bool atCapacity) { return (totalSupply == maxCapacity); @@ -611,7 +615,7 @@ contract Consent is /// @param hash Hashed message containing user address (if restricted opt in), token id and agreementFlags /// @param signature Signature of approved user's message hash /// @return Boolean of whether signature is valid - function _isValidSignature( + function _isValidSignerSignature( bytes32 hash, bytes memory signature ) internal view returns (bool) { @@ -624,6 +628,27 @@ contract Consent is return hasRole(SIGNER_ROLE, signer); } + /// @notice Verify that a signature is valid + /// @param hash Hashed message containing user address (if restricted opt in), token id and agreementFlags + /// @param signature Signature of approved user's message hash + /// @return Boolean of whether signature is valid + function _isValidOptInSignature( + bytes32 hash, + bytes memory signature + ) internal view returns (address) { + // retrieve the signature's signer + address signer = ECDSAUpgradeable.recover(hash, signature); + + require(signer != address(0), "Consent: Signer cannot be 0 address."); + + // check if the recovered signature has a nonzero balance + require( + balanceOf(signer) == 0, + "Consent: User has already opted in" + ); + return signer; + } + /* OVERRIDES */ function _beforeTokenTransfer( @@ -688,35 +713,4 @@ contract Consent is { return super.supportsInterface(interfaceId); } - - function _msgSender() - internal - view - virtual - override(ContextUpgradeable) - returns (address sender) - { - if (isTrustedForwarder(msg.sender)) { - // The assembly code is more direct than the Solidity version using `abi.decode`. - assembly { - sender := shr(96, calldataload(sub(calldatasize(), 20))) - } - } else { - return super._msgSender(); - } - } - - function _msgData() - internal - view - virtual - override(ContextUpgradeable) - returns (bytes calldata) - { - if (isTrustedForwarder(msg.sender)) { - return msg.data[:msg.data.length - 20]; - } else { - return super._msgData(); - } - } -} \ No newline at end of file +} diff --git a/packages/contracts/contracts/consent/IConsent.sol b/packages/contracts/contracts/consent/IConsent.sol index bb8e6ac43f..2ecbcaae67 100644 --- a/packages/contracts/contracts/consent/IConsent.sol +++ b/packages/contracts/contracts/consent/IConsent.sol @@ -42,8 +42,6 @@ interface IConsent { function openOptInDisabled() external view returns(bool); - function trustedForwarder() external view returns(address); - function queryHorizon() external view returns(uint); function agreementFlagsArray(uint256) external view returns(bytes32); @@ -64,7 +62,7 @@ interface IConsent { function removeListing(string memory tag) external returns (string memory); - function optIn(uint256 tokenId, bytes32 agreementFlags) external; + function optIn(uint256 tokenId, bytes32 agreementFlags, bytes32 identityCommitment, bytes memory stealthSignature) external; function restrictedOptIn(uint256 tokenId, bytes32 agreementFlags, bytes memory signature) external; @@ -80,8 +78,6 @@ interface IConsent { function setQueryHorizon(uint queryHorizon_) external; - function updateTrustedForwarder() external; - function updateMaxTagsLimit() external; function setBaseURI(string memory newURI) external; diff --git a/packages/contracts/contracts/metatx/SynamintForwarderUpgradeable.sol b/packages/contracts/contracts/metatx/SynamintForwarderUpgradeable.sol deleted file mode 100644 index 728ff18be0..0000000000 --- a/packages/contracts/contracts/metatx/SynamintForwarderUpgradeable.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/metatx/MinimalForwarderUpgradeable.sol"; -import "hardhat/console.sol"; - -/// @title Upgradeable Syamint Forwarder Contract -/// @author Snickerdoodle Labs -/// @notice Wrapper class for MinimalForwarderUpgradeable.sol to trigger call to initializer function -contract SynamintForwarderUpgradeable is Initializable, MinimalForwarderUpgradeable { - - /// @notice Initializes the MinimalForwarder contract - /// @dev Uses the initializer modifier to to ensure the contract is only initialized once - function initialize() initializer public { - __MinimalForwarder_init(); - } - -} \ No newline at end of file diff --git a/packages/contracts/contracts/registry/Crumbs.sol b/packages/contracts/contracts/registry/Crumbs.sol deleted file mode 100644 index e1b758d266..0000000000 --- a/packages/contracts/contracts/registry/Crumbs.sol +++ /dev/null @@ -1,199 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; - -/// @title Crumbs -/// @author Snickerdoodle Labs -/// @notice Synamint Protocol Crumbs Contract -/// @dev A crumb is a non-transferable ERC721 NFT that holds the JSON object (for SDL's parsing) of a user within the token uri -/// @dev Any user can create a crumb, store and update the JSON object -/// @dev The ERC721's tokenId is labelled crumbId in this contract -/// @dev The baseline contract was generated using OpenZeppelin's (OZ) Contracts Wizard and customized thereafter -/// @dev The contract adopts OZ's upgradeable beacon proxy pattern and serves as an implementation contract -/// @dev It is also compatible with OZ's meta-transaction library - -contract Crumbs is Initializable, AccessControlEnumerableUpgradeable, PausableUpgradeable, ERC721URIStorageUpgradeable, ERC721BurnableUpgradeable { - - /// @dev Trusted forwarder address for meta-transactions - address public trustedForwarder; - - /// @notice Mapping of address to respective crumbId that stores its JSON object - mapping(address => uint256) public addressToCrumbId; - - /// @dev Total supply of Crumb tokens - uint256 public totalSupply; - - /// @dev Base uri of crumbs - string public baseURI; - - /// @notice Emitted when a crumb is created - /// @param owner Indexed address of data requester - /// @param crumbId Indexed crumb id - /// @param tokenURI tokenURI containing JSON object - event CrumbCreated(address indexed owner, uint256 indexed crumbId, string tokenURI); - - /// @notice Emitted when a crumb is burnt - /// @param owner Indexed address of data requester - /// @param crumbId Indexed crumb id - event CrumbBurnt(address indexed owner, uint256 indexed crumbId); - - /// @notice Emitted when a crumb is updated - /// @param owner Indexed address of data requester - /// @param crumbId Indexed crumb id - /// @param tokenURI New token URI - event CrumbUpdated(address indexed owner, uint256 indexed crumbId, string tokenURI); - - /// @notice Initializes the contract - /// @dev Uses the initializer modifier to to ensure the contract is only initialized once - function initialize(address trustedForwarder_, string memory baseURI_) initializer public { - __ERC721_init("Crumbs", "CRU"); - __ERC721URIStorage_init(); - __ERC721Burnable_init(); - __AccessControl_init(); - - trustedForwarder = trustedForwarder_; - - _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); - setBaseURI(baseURI_); - } - - /// @notice Mints user a crumb - /// @param crumbId Id of the crumb token - /// @param _tokenURI String of JSON object - function createCrumb(uint256 crumbId, string memory _tokenURI) public { - require(addressToCrumbId[_msgSender()] == 0, "Crumb: Address already has a crumb"); - - // add address and crumbId to the mapping - addressToCrumbId[_msgSender()] = crumbId; - - // mint the crumb - _safeMint(_msgSender(), crumbId); - // set the JSON object as the crumb's URI - _setTokenURI(crumbId, _tokenURI); - - // increase total supply - totalSupply++; - - emit CrumbCreated(_msgSender(), crumbId, _tokenURI); - } - - /// @notice Burns user's crumb - /// @param crumbId Id of the crumb token - function burnCrumb(uint256 crumbId) public { - // check is caller is the owner of the crumbId and burns if true - burn(crumbId); - // remove the crum id from the mapping - delete addressToCrumbId[_msgSender()]; - // reduce total supply - totalSupply--; - - emit CrumbBurnt(_msgSender(), crumbId); - } - - /// @notice Update a user's crumb - /// @param crumbId Id of the crumb token to update - /// @param _tokenURI Id of the crumb token to update - function updateCrumb(uint256 crumbId, string memory _tokenURI) public { - - require(addressToCrumbId[_msgSender()] == crumbId, "Crumbs: Caller is not crumb id's owner"); - - _setTokenURI(crumbId, _tokenURI); - - emit CrumbUpdated(_msgSender(), crumbId, _tokenURI); - } - - /* SETTERS */ - - /// @notice Sets the Crumb tokens base URI - /// @param newURI New base uri - function setBaseURI(string memory newURI) public onlyRole(DEFAULT_ADMIN_ROLE) { - baseURI = newURI; - } - - /* OVERRIDES */ - - /// @notice Override _baseURI to return the Crumb tokens base URI - function _baseURI() internal view virtual override returns (string memory baseURI_) { - return baseURI; - } - - /// @dev Override to add require statement to make crumb tokens non-transferable - /// @dev Remove an address's mapping to its crumb id once its transferred - function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize) - internal - whenNotPaused - override - { - // ensures crumbs are non-transferable - require(from == address(0) || to == address(0), "Crumbs: Crumb tokens are non-transferrable"); - - // carry out checks before transfer - super._beforeTokenTransfer(from, to, tokenId, batchSize); - - // if checks pass, delete crumb id of sender - delete addressToCrumbId[from]; - - // update crumb id to the receiver - addressToCrumbId[to] = tokenId; - } - - // The following functions are overrides required by Solidity. - - function _burn(uint256 tokenId) - internal - override(ERC721Upgradeable, ERC721URIStorageUpgradeable) - { - super._burn(tokenId); - } - - function tokenURI(uint256 tokenId) - public - view - override(ERC721Upgradeable, ERC721URIStorageUpgradeable) - returns (string memory) - { - return super.tokenURI(tokenId); - } - - function supportsInterface(bytes4 interfaceId) - public - view - override(ERC721Upgradeable, AccessControlEnumerableUpgradeable) - returns (bool) - { - return super.supportsInterface(interfaceId); - } - - /// @dev Inherited from ERC2771ContextUpgradeable to embed its features directly in this contract - /// @dev This is a workaround as ERC2771ContextUpgradeable does not have an _init() function - /// @dev Allows the factory to deploy a BeaconProxy that initiates a Consent contract without a constructor - function isTrustedForwarder(address forwarder) public view virtual returns (bool) { - return forwarder == trustedForwarder; - } - - function _msgSender() internal view virtual override(ContextUpgradeable) returns (address sender) { - if (isTrustedForwarder(msg.sender)) { - // The assembly code is more direct than the Solidity version using `abi.decode`. - assembly { - sender := shr(96, calldataload(sub(calldatasize(), 20))) - } - } else { - return super._msgSender(); - } - } - - function _msgData() internal view virtual override(ContextUpgradeable) returns (bytes calldata) { - if (isTrustedForwarder(msg.sender)) { - return msg.data[:msg.data.length - 20]; - } else { - return super._msgData(); - } - } - -} \ No newline at end of file diff --git a/packages/contracts/contracts/registry/README.md b/packages/contracts/contracts/registry/README.md deleted file mode 100644 index c6dc47bb7a..0000000000 --- a/packages/contracts/contracts/registry/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Snickerdoodle Protocol Registry Contracts - -## Register Contracts List and Function Overview - -- [Crumbs.sol](/packages/contracts/docs/registry/Crumbs.md) - - Serves as an account recovery registry. Users create Crumbs (ERC721 NFTs) and store hashes in the token's URI. These hashes allow users to recover their private keys. -- [Sift.sol](/packages/contracts/docs/registry/Sift.md) - - Serves as a URL verification registry. URLs stored on this contract are minted a Sift token (ERC721 NFT) and tagged as VERIFIED or MALICIOUS in its token URI. diff --git a/packages/contracts/contracts/registry/Sift.sol b/packages/contracts/contracts/registry/Sift.sol deleted file mode 100644 index f0b813f374..0000000000 --- a/packages/contracts/contracts/registry/Sift.sol +++ /dev/null @@ -1,154 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; - -/// @title Sift -/// @author Snickerdoodle Labs -/// @notice Synamint Protocol Sift Contract -/// @dev The Sift contract is a simple registry that tracks verified or malicious urls -/// @dev If a url has been verified by the Snickerdoodle team, it is minted with a Sift ERC721 token with a 'VERIFIED' tokenURI -/// @dev If a url has been identified as malicious, it is minted a 'MALICIOUS' tokenURI -/// @dev SDL's data wallet browser extension will query the Sift contract with the url that its user is visiting -/// @dev Each url that enters the registry is mapped to a token id that has the corresponding tokenURI describe above -/// @dev If the url does not have a tokenId minted against it, the contract returns the 'NOT VERIFIED' status - -contract Sift is Initializable, ERC721Upgradeable, ERC721URIStorageUpgradeable, ERC721BurnableUpgradeable, AccessControlEnumerableUpgradeable { - using CountersUpgradeable for CountersUpgradeable.Counter; - - CountersUpgradeable.Counter private _tokenIdCounter; - - /// @dev mapping of hashed url to tokenId - mapping(bytes32 => uint256) public urlToTokenId; - - /// @dev Base uri of Sift - string public baseURI; - - /// @dev Total supply of Sift tokens - uint256 public totalSupply; - - /// @dev Role bytes - bytes32 public constant VERIFIER_ROLE = keccak256("VERIFIER_ROLE"); - - /// @dev Initializes the contract with the base URI, then disables any initializers as recommended by OpenZeppelin - constructor(string memory baseURInew) { - initialize(baseURInew); - } - - /// @notice Initializes the contract - /// @dev Uses the initializer modifier to to ensure the contract is only initialized once - function initialize(string memory baseURI_) initializer public { - __ERC721_init("Sift", "SIFT"); - __ERC721URIStorage_init(); - __ERC721Burnable_init(); - - _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); - _grantRole(VERIFIER_ROLE, msg.sender); - - setBaseURI(baseURI_); - } - - /// @notice Verifies a url - /// @dev Mints an NFT with the 'VERIFIED' tokenURI - /// @dev Only addresses with VERIFIER_ROLE can call it and is checked in _safeMintAndRegister() - /// @param url Site URL - /// @param owner Address receiving the url's NFT - function verifyURL(string memory url, address owner) external { - // check if the url has already been verified on the contract - // if it has a token id mapped to it, it has been verified - require(urlToTokenId[keccak256(abi.encodePacked(url))] == 0, "Consent: URL already verified"); - - // mint token id and append to the token URI "VERIFIED" - _safeMintAndRegister(owner, "VERIFIED", url); - } - - /// @notice Marks a url as malicious - /// @dev Mints an NFT with the 'MALICIOUS' tokenURI - /// @dev Only addresses with VERIFIER_ROLE can call it and is checked in _safeMintAndRegister() - /// @param url Site URL - /// @param owner Address receiving the url's NFT - function maliciousURL(string memory url, address owner) external { - // mint token id and append to the token URI "MALICIOUS" - _safeMintAndRegister(owner, "MALICIOUS", url); - } - - /// @notice Checks the status of a url - /// @param url Site URL - /// @return result Returns the token uri of 'VERIFIED', 'MALICIOUS', or 'NOT VERIFIED' - function checkURL(string memory url) external view returns(string memory result) { - // get the url's token using its hashed value - uint256 tokenId = urlToTokenId[keccak256(abi.encodePacked(url))]; - - // if token's id is 0, it has not been verified yet - if (tokenId == 0) return "NOT VERIFIED"; - - // else, return token's URI - return tokenURI(tokenId); - } - - /// @notice Sets the Sift tokens base URI - /// @param newURI New base uri - function setBaseURI(string memory newURI) public onlyRole(DEFAULT_ADMIN_ROLE) { - baseURI = newURI; - } - - /// @notice Internal function to carry out token minting and mapping updates - /// @param to Address receiving the token - /// @param uri Token uri containing status - /// @param url Site URL - function _safeMintAndRegister(address to, string memory uri, string memory url) internal onlyRole(VERIFIER_ROLE) { - // ensure that tokenIds start from 1 so that 0 can be kept as tokens that are not verified yet - uint256 tokenId = _tokenIdCounter.current() + 1; - _tokenIdCounter.increment(); - _safeMint(to, tokenId); - _setTokenURI(tokenId, uri); - - // register hashed url to token mapping - urlToTokenId[keccak256(abi.encodePacked(url))] = tokenId; - - /// increase total supply count - totalSupply++; - } - - /* OVERRIDES */ - - /// @notice Override _baseURI to return the Sift tokens base URI - function _baseURI() internal view virtual override returns (string memory baseURI_) { - return baseURI; - } - - // The following functions are overrides required by Solidity. - - function _burn(uint256 tokenId) - internal - override(ERC721Upgradeable, ERC721URIStorageUpgradeable) - { - super._burn(tokenId); - - /// decrease total supply count - totalSupply--; - } - - function tokenURI(uint256 tokenId) - public - view - override(ERC721Upgradeable, ERC721URIStorageUpgradeable) - returns (string memory) - { - return super.tokenURI(tokenId); - } - - function supportsInterface(bytes4 interfaceId) - public - view - override(ERC721Upgradeable, AccessControlEnumerableUpgradeable) - returns (bool) - { - return super.supportsInterface(interfaceId); - } -} \ No newline at end of file diff --git a/packages/contracts/contracts/token/DoodleToken.sol b/packages/contracts/contracts/token/DoodleToken.sol index a228d8447f..6d45d49538 100644 --- a/packages/contracts/contracts/token/DoodleToken.sol +++ b/packages/contracts/contracts/token/DoodleToken.sol @@ -14,8 +14,8 @@ import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol"; contract DoodleToken is ERC20, ERC20Permit, ERC20Votes { constructor(address distributionAddress) ERC20("Doodle", "DOODLE") ERC20Permit("Doodle") { - // TODO: confirm total cap supply, mints to foundation/DAO/treasury address - _mint(distributionAddress, 100000000000000000000000000); + // total initial supply is 13.5 billion tokens with 18 decimal places of precision + _mint(distributionAddress, 13500000000e18); } // The following functions are overrides required by Solidity. From 250b6397584e3797ff887b5b5d0e57c7ceb2e3b3 Mon Sep 17 00:00:00 2001 From: TtheBC01 Date: Tue, 5 Sep 2023 11:29:03 -0700 Subject: [PATCH 5/6] fixed consent interface --- packages/contracts/contracts/consent/IConsent.sol | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/contracts/contracts/consent/IConsent.sol b/packages/contracts/contracts/consent/IConsent.sol index 2ecbcaae67..b5a762abb9 100644 --- a/packages/contracts/contracts/consent/IConsent.sol +++ b/packages/contracts/contracts/consent/IConsent.sol @@ -52,6 +52,9 @@ interface IConsent { function getTagArray() external view returns (Tag[] memory); + function getDomains() external view returns (string[] memory); + + // ranking engine functions function newGlobalTag(string memory tag, uint256 _newSlot) external; function newLocalTagUpstream(string memory tag, uint256 _newSlot, uint256 _existingSlot) external; @@ -62,16 +65,18 @@ interface IConsent { function removeListing(string memory tag) external returns (string memory); + // Opt-in and Opt-out methods & query methods function optIn(uint256 tokenId, bytes32 agreementFlags, bytes32 identityCommitment, bytes memory stealthSignature) external; - function restrictedOptIn(uint256 tokenId, bytes32 agreementFlags, bytes memory signature) external; + function restrictedOptIn(uint256 tokenId, bytes32 agreementFlags, bytes32 identityCommitment, bytes memory stealthSignature, bytes memory signature) external; - function anonymousRestrictedOptIn(uint256 tokenId, bytes32 agreementFlags, bytes memory signature) external; + function anonymousRestrictedOptIn(uint256 tokenId, bytes32 agreementFlags, bytes32 identityCommitment, bytes memory stealthSignature, bytes memory signature) external; function optOut(uint256 tokenId) external; function requestForData(string memory ipfsCID) external; + // parameter updating functions function updateMaxCapacity(uint _maxCapacity) external; function updateAgreementFlags(uint256 tokenId, bytes32 newAgreementFlags) external; @@ -92,7 +97,5 @@ interface IConsent { function disableOpenOptIn() external; - function enableOpenOptIn() external; - - function getDomains() external view returns (string[] memory); + function enableOpenOptIn() external; } \ No newline at end of file From e660a829b518d0a99c4650bb09151c0f3e61bbab Mon Sep 17 00:00:00 2001 From: Todd Chapman <6946868+TtheBC01@users.noreply.github.com> Date: Wed, 13 Sep 2023 10:27:06 -0700 Subject: [PATCH 6/6] Update consent-stack-only.js --- packages/contracts/scripts/consent-stack-only.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/contracts/scripts/consent-stack-only.js b/packages/contracts/scripts/consent-stack-only.js index 0837dc5dbf..a4f95e4ecc 100644 --- a/packages/contracts/scripts/consent-stack-only.js +++ b/packages/contracts/scripts/consent-stack-only.js @@ -6,7 +6,6 @@ const { ethers, upgrades } = require("hardhat"); // declare variables that need to be referenced by other functions -let trustedForwarderAddress = "0xdB5c885944d903Ac5c146eef400D2ee20572d357"; let consentAddress; async function deployMinimalForwarder() { @@ -57,7 +56,6 @@ async function deployConsentFactory() { // function that runs the full deployment of all contracts async function fullDeployment() { - //await deployMinimalForwarder(); await deployConsent(); await deployConsentFactory();