Skip to content

Commit

Permalink
feat: InvoiceManager creates invoices
Browse files Browse the repository at this point in the history
  • Loading branch information
Haypierre committed Jan 10, 2025
1 parent fd83278 commit 82448c8
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 49 deletions.
16 changes: 12 additions & 4 deletions src/core/InvoiceManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ contract InvoiceManager is UUPSUpgradeable, OwnableUpgradeable, ReentrancyGuardU

function _authorizeUpgrade(address) internal override onlyOwner {}

modifier onlyPaymaster(address account) {
require(cabPaymasters[account].paymaster == msg.sender, "InvoiceManager: caller is not the paymaster");
_;
}

/// @inheritdoc IInvoiceManager
function registerPaymaster(address paymaster, IPaymasterVerifier paymasterVerifier, uint256 expiry)
external
Expand All @@ -61,14 +66,17 @@ contract InvoiceManager is UUPSUpgradeable, OwnableUpgradeable, ReentrancyGuardU
}

/// @inheritdoc IInvoiceManager
function createInvoice(uint256 nonce, address paymaster, bytes32 invoiceId) external override {
function createInvoice(uint256 nonce, address account, bytes32 invoiceId)
external
override
onlyPaymaster(account)
{
// check if the invoice already exists
require(invoices[invoiceId].account == address(0), "InvoiceManager: invoice already exists");

// store the invoice
invoices[invoiceId] = Invoice(msg.sender, nonce, paymaster, block.chainid);
invoices[invoiceId] = Invoice(account, nonce, msg.sender, block.chainid);

emit InvoiceCreated(invoiceId, msg.sender, paymaster);
emit InvoiceCreated(invoiceId, account, msg.sender);
}

/// @inheritdoc IInvoiceManager
Expand Down
6 changes: 0 additions & 6 deletions src/interfaces/IPaymasterVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ import {IInvoiceManager} from "./IInvoiceManager.sol";
* @title Interface for the PaymasterVerifier contract.
*/
interface IPaymasterVerifier {
/// @notice Emitted when an invoice is created.
event InvoiceCreated(bytes32 indexed invoiceId);

/// @notice Emitted when an invoice is verified.
event InvoiceVerified(bytes32 indexed invoiceId);

/// @notice The struct of the sponsor token.
struct SponsorToken {
address token;
Expand Down
27 changes: 14 additions & 13 deletions src/paymasters/CABPaymaster.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,10 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {

(uint256 logIndex, bytes memory proof) = abi.decode(_proof, (uint256, bytes));
(,, bytes[] memory topics,) = crossL2Prover.validateEvent(logIndex, proof);
bytes[] memory expectedTopics = new bytes[](2);
expectedTopics[0] = abi.encode(InvoiceCreated.selector);
expectedTopics[1] = abi.encode(invoiceId);

if (!LibBytes.eq(abi.encode(topics), abi.encode(expectedTopics))) {
return false;
}
emit InvoiceVerified(invoiceId);
return true;
return LibBytes.eq(
abi.encode(topics[0], topics[1]), abi.encode(IInvoiceManager.InvoiceCreated.selector, invoiceId)
);
}

function withdraw(address token, uint256 amount) external override onlyOwner {
Expand Down Expand Up @@ -144,13 +139,17 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
// don't revert on signature failure: return SIG_VALIDATION_FAILED
if (verifyingSigner != ECDSA.recover(hash, paymasterSignature)) {
return (
abi.encodePacked(invoiceId, sponsorTokenData[0:1 + sponsorTokenLength * 72]),
abi.encodePacked(
invoiceId, userOp.getSender(), userOp.nonce, sponsorTokenData[0:1 + sponsorTokenLength * 72]
),
_packValidationData(true, validUntil, validAfter)
);
}

return (
abi.encodePacked(invoiceId, sponsorTokenData[0:1 + sponsorTokenLength * 72]),
abi.encodePacked(
invoiceId, userOp.getSender(), userOp.nonce, sponsorTokenData[0:1 + sponsorTokenLength * 72]
),
_packValidationData(false, validUntil, validAfter)
);
}
Expand All @@ -160,8 +159,7 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
virtual
override
{
bytes32 invoiceId = bytes32(context[:32]);
bytes calldata sponsorTokenData = context[32:];
bytes calldata sponsorTokenData = context[84:];

(uint8 sponsorTokenLength, SponsorToken[] memory sponsorTokens) = parseSponsorTokenData(sponsorTokenData);
for (uint8 i = 0; i < sponsorTokenLength; i++) {
Expand All @@ -170,7 +168,10 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
}
// TODO: Batch Proving Optimistation -> write in settlement contract on `opSucceeded`
if (mode == PostOpMode.opSucceeded) {
emit InvoiceCreated(invoiceId);
bytes32 invoiceId = bytes32(context[:32]);
address account = address(bytes20(context[32:52]));
uint256 nonce = uint256(bytes32(context[52:84]));
invoiceManager.createInvoice(nonce, account, invoiceId);
}
}

Expand Down
Loading

0 comments on commit 82448c8

Please sign in to comment.