From fdc2bf6a1504c976ebc1d7155939272e407e2151 Mon Sep 17 00:00:00 2001 From: livingrockrises <90545960+livingrockrises@users.noreply.github.com> Date: Thu, 21 Mar 2024 20:39:35 +0400 Subject: [PATCH] setup --- contracts/common/Errors.sol | 16 +++++ .../IBiconomySponsorshipPaymaster.sol | 16 +++++ .../SponsorshipPaymasterWithPremium.sol | 61 ++++++++++++++++++- contracts/utils/SoladyOwnable.sol | 10 +++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 contracts/common/Errors.sol create mode 100644 contracts/interfaces/IBiconomySponsorshipPaymaster.sol create mode 100644 contracts/utils/SoladyOwnable.sol diff --git a/contracts/common/Errors.sol b/contracts/common/Errors.sol new file mode 100644 index 0000000..0454090 --- /dev/null +++ b/contracts/common/Errors.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.24; + +contract BiconomySponsorshipPaymasterErrors { + + /** + * @notice Throws when the paymaster address provided is address(0) + */ + error PaymasterIdCannotBeZero(); + + /** + * @notice Throws when the 0 has been provided as deposit + */ + error DepositCanNotBeZero(); + +} \ No newline at end of file diff --git a/contracts/interfaces/IBiconomySponsorshipPaymaster.sol b/contracts/interfaces/IBiconomySponsorshipPaymaster.sol new file mode 100644 index 0000000..af0feda --- /dev/null +++ b/contracts/interfaces/IBiconomySponsorshipPaymaster.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +interface IBiconomySponsorshipPaymaster { + event FixedPriceMarkupChanged(uint32 indexed _oldValue, uint32 indexed _newValue); + + event VerifyingSignerChanged(address indexed _oldSigner, address indexed _newSigner, address indexed _actor); + + event FeeCollectorChanged( + address indexed _oldFeeCollector, address indexed _newFeeCollector, address indexed _actor + ); + event GasDeposited(address indexed _paymasterId, uint256 indexed _value); + event GasWithdrawn(address indexed _paymasterId, address indexed _to, uint256 indexed _value); + event GasBalanceDeducted(address indexed _paymasterId, uint256 indexed _charge, bytes32 indexed userOpHash); + event PremiumCollected(address indexed _paymasterId, uint256 indexed _premium); +} \ No newline at end of file diff --git a/contracts/sponsorship/SponsorshipPaymasterWithPremium.sol b/contracts/sponsorship/SponsorshipPaymasterWithPremium.sol index 45d6c39..898e127 100644 --- a/contracts/sponsorship/SponsorshipPaymasterWithPremium.sol +++ b/contracts/sponsorship/SponsorshipPaymasterWithPremium.sol @@ -9,4 +9,63 @@ import "account-abstraction/contracts/core/Helpers.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import { SignatureCheckerLib } from "solady/src/utils/SignatureCheckerLib.sol"; -import { ECDSA as ECDSA_solady } from "solady/src/utils/ECDSA.sol"; \ No newline at end of file +import { ECDSA as ECDSA_solady } from "solady/src/utils/ECDSA.sol"; +import { BiconomySponsorshipPaymasterErrors } from "../common/Errors.sol"; +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import { IBiconomySponsorshipPaymaster } from "../interfaces/IBiconomySponsorshipPaymaster.sol"; + +// possiblity (conflicts with BasePaymaster which is also Ownbale) // either make BasePaymaster SoladyOwnable +// import { SoladyOwnable } from "../utils/SoladyOwnable.sol"; + +/** + * @title BiconomySponsorshipPaymaster + * @author livingrockrises + * @notice Based on Infinitism 'VerifyingPaymaster' contract + * @dev This contract is used to sponsor the transaction fees of the user operations + * Uses a verifying signer to provide the signature if predetermined conditions are met + * regarding the user operation calldata. Also this paymaster is Singleton in nature which + * means multiple Dapps/Wallet clients willing to sponsor the transactions can share this paymaster. + * Maintains it's own accounting of the gas balance for each Dapp/Wallet client + * and Manages it's own deposit on the EntryPoint. + */ + +// Todo: Add more methods in interface +// Todo: Add methods to withdraw stuck erc20 tokens and native tokens + +abstract contract BiconomySponsorshipPaymaster is BasePaymaster, ReentrancyGuard, BiconomySponsorshipPaymasterErrors, IBiconomySponsorshipPaymaster { + using UserOperationLib for PackedUserOperation; + + address public verifyingSigner; + address public feeCollector; + uint32 private constant PRICE_DENOMINATOR = 1e6; + + // note: could rename to PAYMASTER_ID_OFFSET + uint256 private constant VALID_PND_OFFSET = PAYMASTER_DATA_OFFSET; + + // temp + // paymasterAndData: paymaster address + paymaster gas limits + paymasterData + // paymasterData: concat of [paymasterId(20 bytes), validUntil(6 bytes), validAfter(6 bytes), priceMarkup(4 bytes), signature] + + mapping(address => uint256) public paymasterIdBalances; + + constructor(address _owner, IEntryPoint _entryPoint, address _verifyingSigner, address _feeCollector) BasePaymaster(_entryPoint) { + // TODO + // Check for zero address + verifyingSigner = _verifyingSigner; + feeCollector = _feeCollector; + _transferOwnership(_owner); + } + + /** + * @dev Add a deposit for this paymaster and given paymasterId (Dapp Depositor address), used for paying for transaction fees + * @param paymasterId dapp identifier for which deposit is being made + */ + function depositFor(address paymasterId) external payable nonReentrant { + if (paymasterId == address(0)) revert PaymasterIdCannotBeZero(); + if (msg.value == 0) revert DepositCanNotBeZero(); + paymasterIdBalances[paymasterId] += msg.value; + entryPoint.depositTo{value: msg.value}(address(this)); + emit GasDeposited(paymasterId, msg.value); + } + +} \ No newline at end of file diff --git a/contracts/utils/SoladyOwnable.sol b/contracts/utils/SoladyOwnable.sol new file mode 100644 index 0000000..9589b3d --- /dev/null +++ b/contracts/utils/SoladyOwnable.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {Ownable} from "solady/src/auth/Ownable.sol"; + +contract SoladyOwnable is Ownable { + constructor(address _owner) Ownable() { + _initializeOwner(_owner); + } +} \ No newline at end of file