Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
5bb0ade5
Commit
5bb0ade5
authored
Mar 28, 2023
by
James Kim
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
store invite counts in storage instead of on AttestationStation
parent
2bc08bc7
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
30 additions
and
67 deletions
+30
-67
OptimistInviter.t.sol
...s-periphery/contracts/foundry-tests/OptimistInviter.t.sol
+8
-37
OptimistInviter.sol
...-periphery/contracts/universal/op-nft/OptimistInviter.sol
+22
-30
No files found.
packages/contracts-periphery/contracts/foundry-tests/OptimistInviter.t.sol
View file @
5bb0ade5
...
...
@@ -97,12 +97,7 @@ contract OptimistInviter_Initializer is Test {
* @notice Returns a user's current invite count, as stored in the AttestationStation.
*/
function _getInviteCount(address _issuer) internal view returns (uint256) {
bytes memory attestation = attestationStation.attestations(
address(optimistInviter),
_issuer,
optimistInviter.CAN_INVITE_ATTESTATION_KEY()
);
return abi.decode(attestation, (uint256));
return optimistInviter.inviteCounts(_issuer);
}
/**
...
...
@@ -226,15 +221,6 @@ contract OptimistInviter_Initializer is Test {
abi.encode(issuer)
);
// OptimistInviter should issue a new attestation with updated invite count
vm.expectEmit(true, true, true, true, address(attestationStation));
emit AttestationCreated(
address(optimistInviter),
issuer,
optimistInviter.CAN_INVITE_ATTESTATION_KEY(),
abi.encode(prevInviteCount - 1)
);
// Should emit an event indicating that the invite was claimed
vm.expectEmit(true, false, false, false, address(optimistInviter));
emit InviteClaimed(issuer, _claimer);
...
...
@@ -267,7 +253,7 @@ contract OptimistInviter_Initializer is Test {
address(optimistInviter),
_to,
optimistInviter.CAN_INVITE_ATTESTATION_KEY(),
abi.encode(3
)
bytes("true"
)
);
vm.prank(alice_inviteGranter);
...
...
@@ -319,7 +305,7 @@ contract OptimistInviterTest is OptimistInviter_Initializer {
address(optimistInviter),
bob,
optimistInviter.CAN_INVITE_ATTESTATION_KEY(),
abi.encode(3
)
bytes("true"
)
);
vm.expectEmit(true, true, true, true, address(attestationStation));
...
...
@@ -327,7 +313,7 @@ contract OptimistInviterTest is OptimistInviter_Initializer {
address(optimistInviter),
sally,
optimistInviter.CAN_INVITE_ATTESTATION_KEY(),
abi.encode(3
)
bytes("true"
)
);
vm.expectEmit(true, true, true, true, address(attestationStation));
...
...
@@ -335,7 +321,7 @@ contract OptimistInviterTest is OptimistInviter_Initializer {
address(optimistInviter),
address(carolERC1271Wallet),
optimistInviter.CAN_INVITE_ATTESTATION_KEY(),
abi.encode(3
)
bytes("true"
)
);
vm.prank(alice_inviteGranter);
...
...
@@ -419,21 +405,14 @@ contract OptimistInviterTest is OptimistInviter_Initializer {
abi.encode(bob)
);
// OptimistInviter should issue a new attestation with updated invite count
vm.expectEmit(true, true, true, true, address(attestationStation));
emit AttestationCreated(
address(optimistInviter),
bob,
optimistInviter.CAN_INVITE_ATTESTATION_KEY(),
abi.encode(2)
);
// Should emit an event indicating that the invite was claimed
vm.expectEmit(true, true, true, true, address(optimistInviter));
emit InviteClaimed(bob, sally);
vm.prank(eve);
optimistInviter.claimInvite(sally, claimableInvite, signature);
assertEq(_getInviteCount(bob), 2);
assertTrue(_hasMintAttestation(sally));
assertFalse(_hasMintAttestation(eve));
}
...
...
@@ -560,17 +539,9 @@ contract OptimistInviterTest is OptimistInviter_Initializer {
abi.encode(address(carolERC1271Wallet))
);
// OptimistInviter should issue a new attestation with updated invite count
vm.expectEmit(true, true, true, true, address(attestationStation));
emit AttestationCreated(
address(optimistInviter),
address(carolERC1271Wallet),
optimistInviter.CAN_INVITE_ATTESTATION_KEY(),
abi.encode(2)
);
vm.prank(sally);
optimistInviter.claimInvite(sally, claimableInvite, signature);
assertEq(_getInviteCount(address(carolERC1271Wallet)), 2);
}
/**
...
...
packages/contracts-periphery/contracts/universal/op-nft/OptimistInviter.sol
View file @
5bb0ade5
...
...
@@ -12,9 +12,9 @@ import {
* @custom:upgradeable
* @title OptimistInviter
* @notice OptimistInviter issues "optimist.can-invite" and "optimist.can-mint-from-invite"
* attestations. Accounts that have
a "optimist.can-invite" attestation can issue
*
signatures that allow other accounts to claim an invite. The invitee uses a claim
*
and reveal flow to claim the
invite to an address of their choosing.
* attestations. Accounts that have
invites can issue signatures that allow other
*
accounts to claim an invite. The invitee uses a claim and reveal flow to claim the
* invite to an address of their choosing.
*
* Parties involved:
* 1) INVITE_GRANTER: trusted account that can allow accounts to issue invites
...
...
@@ -23,7 +23,7 @@ import {
*
* Flow:
* 1) INVITE_GRANTER calls _setInviteCount to allow an issuer to issue a certain number
* of invites,
creating "optimist.can-invite" attestations
for the issuer
* of invites,
and also creates a "optimist.can-invite" attestation
for the issuer
* 2) Off-chain, the issuer signs (EIP-712) a ClaimableInvite to produce a signature
* 3) Off-chain, invite issuer sends the plaintext ClaimableInvite and the signature
* to the recipient
...
...
@@ -50,7 +50,7 @@ contract OptimistInviter is Semver, EIP712Upgradeable {
keccak256("ClaimableInvite(address issuer,bytes32 nonce)");
/**
* @notice Attestation key for
granting invites.
* @notice Attestation key for
that signals that an account was allowed to issue invites
*/
bytes32 public constant CAN_INVITE_ATTESTATION_KEY = keccak256("optimist.can-invite");
...
...
@@ -95,6 +95,11 @@ contract OptimistInviter is Semver, EIP712Upgradeable {
*/
mapping(address => mapping(bytes32 => bool)) public usedNonces;
/**
* @notice Maps from addresses to number of invites they have.
*/
mapping(address => uint256) public inviteCounts;
/**
* @custom:semver 1.0.0
*
...
...
@@ -140,13 +145,14 @@ contract OptimistInviter is Semver, EIP712Upgradeable {
memory attestations = new AttestationStation.AttestationData[](length);
for (uint256 i; i < length; ) {
// The granted invites are stored as an attestation from this contract on the
// AttestationStation contract. Number of invites is stored as a encoded uint256 in the
// data field of the attestation.
// Set invite count for account to _inviteCount
inviteCounts[_accounts[i]] = _inviteCount;
// Create an attestation for posterity that the account is allowed to create invites
attestations[i] = AttestationStation.AttestationData({
about: _accounts[i],
key: CAN_INVITE_ATTESTATION_KEY,
val:
abi.encode(_inviteCount
)
val:
bytes("true"
)
});
unchecked {
...
...
@@ -235,24 +241,16 @@ contract OptimistInviter is Semver, EIP712Upgradeable {
// Set the nonce as used for the issuer so that it cannot be replayed.
usedNonces[_claimableInvite.issuer][_claimableInvite.nonce] = true;
// Check the AttestationStation contract to see how many invites the issuer has left.
bytes memory attestation = ATTESTATION_STATION.attestations(
address(this),
_claimableInvite.issuer,
CAN_INVITE_ATTESTATION_KEY
);
// Failing this check means that the issuer was never granted any invites to begin with.
require(attestation.length > 0, "OptimistInviter: issuer has no invites");
uint256 count = abi.decode(attestation, (uint256));
// Failing this check means that the issuer has used up all of their existing invites.
require(count > 0, "OptimistInviter: issuer has no invites");
require(
inviteCounts[_claimableInvite.issuer] > 0,
"OptimistInviter: issuer has no invites"
);
// Reduce the issuer's invite count by 1
by re-attesting the optimist.can-invite attestation
//
with the new count. Can be unchecked because we check that the count is > 0 above
.
// Reduce the issuer's invite count by 1
. Can be unchecked because we check above that
//
count is > 0
.
unchecked {
--
count
;
--
inviteCounts[_claimableInvite.issuer]
;
}
// Create the attestation that the claimer can mint from the issuer's invite.
...
...
@@ -263,12 +261,6 @@ contract OptimistInviter is Semver, EIP712Upgradeable {
abi.encode(_claimableInvite.issuer)
);
ATTESTATION_STATION.attest(
_claimableInvite.issuer,
CAN_INVITE_ATTESTATION_KEY,
abi.encode(count)
);
emit InviteClaimed(_claimableInvite.issuer, _claimer);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment