Skip to content

Commit

Permalink
make tests more modular
Browse files Browse the repository at this point in the history
  • Loading branch information
ShivaanshK committed Jul 8, 2024
1 parent 7234ab1 commit 5ad5619
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 134 deletions.
22 changes: 11 additions & 11 deletions contracts/sponsorship/SponsorshipPaymasterWithPremium.sol
Original file line number Diff line number Diff line change
Expand Up @@ -234,23 +234,23 @@ contract BiconomySponsorshipPaymaster is
/// @param actualGasCost The actual gas cost of the transaction.
function _postOp(PostOpMode, bytes calldata context, uint256 actualGasCost, uint256) internal override {
unchecked {
(address paymasterId, uint32 dynamicMarkup, bytes32 userOpHash) =
(address paymasterId, uint32 dynamicAdjustment, bytes32 userOpHash) =
abi.decode(context, (address, uint32, bytes32));

uint256 costIncludingPremium = (actualGasCost * dynamicMarkup) / PRICE_DENOMINATOR;
uint256 adjustedGasCost = (actualGasCost * dynamicAdjustment) / PRICE_DENOMINATOR;

// deduct with premium
paymasterIdBalances[paymasterId] -= costIncludingPremium;
// Deduct the adjusted cost
paymasterIdBalances[paymasterId] -= adjustedGasCost;

if (costIncludingPremium > actualGasCost) {
// "collect" premium
uint256 actualPremium = costIncludingPremium - actualGasCost;
paymasterIdBalances[feeCollector] += actualPremium;
// Review if we should emit balToDeduct as well
emit PremiumCollected(paymasterId, actualPremium);
if (adjustedGasCost > actualGasCost) {
// Add premium to fee
uint256 premium = adjustedGasCost - actualGasCost;
paymasterIdBalances[feeCollector] += premium;
// Review if we should emit adjustedGasCost as well
emit PremiumCollected(paymasterId, premium);
}

emit GasBalanceDeducted(paymasterId, costIncludingPremium, userOpHash);
emit GasBalanceDeducted(paymasterId, adjustedGasCost, userOpHash);
}
}

Expand Down
62 changes: 62 additions & 0 deletions test/foundry/base/NexusTestBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,46 @@ abstract contract NexusTestBase is CheatCodes, BaseEventsAndErrors {
postopGasLimit = postopGasLimit - gasleft();
}

function createUserOp(
Vm.Wallet memory sender,
BiconomySponsorshipPaymaster paymaster,
uint32 premium
)
internal
returns (PackedUserOperation memory userOp, bytes32 userOpHash)
{
// Create userOp with no paymaster gas estimates
uint48 validUntil = uint48(block.timestamp + 1 days);
uint48 validAfter = uint48(block.timestamp);

userOp = buildUserOpWithCalldata(sender, "", address(VALIDATOR_MODULE));

userOp.paymasterAndData = generateAndSignPaymasterData(
userOp, PAYMASTER_SIGNER, paymaster, 3e6, 3e6, DAPP_ACCOUNT.addr, validUntil, validAfter, premium
);
userOp.signature = signUserOp(sender, userOp);

// Estimate paymaster gas limits
userOpHash = ENTRYPOINT.getUserOpHash(userOp);
(uint256 validationGasLimit, uint256 postopGasLimit) =
estimatePaymasterGasCosts(paymaster, userOp, userOpHash, 5e4);

// Ammend the userop to have new gas limits and signature
userOp.paymasterAndData = generateAndSignPaymasterData(
userOp,
PAYMASTER_SIGNER,
paymaster,
uint128(validationGasLimit),
uint128(postopGasLimit),
DAPP_ACCOUNT.addr,
validUntil,
validAfter,
premium
);
userOp.signature = signUserOp(sender, userOp);
userOpHash = ENTRYPOINT.getUserOpHash(userOp);
}

/// @notice Generates and signs the paymaster data for a user operation.
/// @dev This function prepares the `paymasterAndData` field for a `PackedUserOperation` with the correct signature.
/// @param userOp The user operation to be signed.
Expand Down Expand Up @@ -417,4 +457,26 @@ abstract contract NexusTestBase is CheatCodes, BaseEventsAndErrors {
}
return result;
}

function getPremiums(
BiconomySponsorshipPaymaster paymaster,
uint256 initialDappPaymasterBalance,
uint256 initialFeeCollectorBalance,
uint32 premium
)
internal
view
returns (uint256 expectedPremium, uint256 actualPremium)
{
uint256 resultingDappPaymasterBalance = paymaster.getBalance(DAPP_ACCOUNT.addr);
uint256 resultingFeeCollectorPaymasterBalance = paymaster.getBalance(PAYMASTER_FEE_COLLECTOR.addr);

uint256 totalGasFeesCharged = initialDappPaymasterBalance - resultingDappPaymasterBalance;

if (premium >= 1e6) {
//premium
expectedPremium = totalGasFeesCharged - ((totalGasFeesCharged * 1e6) / premium);
actualPremium = resultingFeeCollectorPaymasterBalance - initialFeeCollectorBalance;
} else revert("Premium must be more than 1e6");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,111 +134,51 @@ contract TestSponsorshipPaymasterWithPremium is NexusTestBase {
bicoPaymaster.deposit{ value: 1 ether }();
}

function test_WithdrawTo() external prankModifier(DAPP_ACCOUNT.addr) {
uint256 initialDappPaymasterBalance = 10 ether;
bicoPaymaster.depositFor{ value: initialDappPaymasterBalance }(DAPP_ACCOUNT.addr);

PackedUserOperation[] memory ops = new PackedUserOperation[](1);

uint48 validUntil = uint48(block.timestamp + 1 days);
uint48 validAfter = uint48(block.timestamp);

PackedUserOperation memory userOp = buildUserOpWithCalldata(ALICE, "", address(VALIDATOR_MODULE));

// No premium
function test_ValidatePaymasterAndPostOpWithoutPremium() external prankModifier(DAPP_ACCOUNT.addr) {
bicoPaymaster.depositFor{ value: 10 ether }(DAPP_ACCOUNT.addr);
// No premoium
uint32 premium = 1e6;
userOp.paymasterAndData = generateAndSignPaymasterData(
userOp, PAYMASTER_SIGNER, bicoPaymaster, 3e6, 3e6, DAPP_ACCOUNT.addr, validUntil, validAfter, premium
);
userOp.signature = signUserOp(ALICE, userOp);

// Estimate paymaster gas limits
bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp);
(uint256 validationGasLimit, uint256 postopGasLimit) =
estimatePaymasterGasCosts(bicoPaymaster, userOp, userOpHash, 5e4);

// Ammend the userop to have new gas limits and signature
userOp.paymasterAndData = generateAndSignPaymasterData(
userOp,
PAYMASTER_SIGNER,
bicoPaymaster,
uint128(validationGasLimit),
uint128(postopGasLimit),
DAPP_ACCOUNT.addr,
validUntil,
validAfter,
premium
);
userOp.signature = signUserOp(ALICE, userOp);
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
(PackedUserOperation memory userOp, bytes32 userOpHash) = createUserOp(ALICE, bicoPaymaster, premium);
ops[0] = userOp;
userOpHash = ENTRYPOINT.getUserOpHash(userOp);

uint256 initialDappPaymasterBalance = bicoPaymaster.getBalance(DAPP_ACCOUNT.addr);
uint256 initialFeeCollectorBalance = bicoPaymaster.getBalance(PAYMASTER_FEE_COLLECTOR.addr);

vm.expectEmit(true, false, true, true, address(bicoPaymaster));
emit IBiconomySponsorshipPaymaster.GasBalanceDeducted(DAPP_ACCOUNT.addr, 0, userOpHash);
ENTRYPOINT.handleOps(ops, payable(BUNDLER.addr));

uint256 resultingDappPaymasterBalance = bicoPaymaster.getBalance(DAPP_ACCOUNT.addr);
assertNotEq(initialDappPaymasterBalance, resultingDappPaymasterBalance);
(uint256 expectedPremium, uint256 actualPremium) =
getPremiums(bicoPaymaster, initialDappPaymasterBalance, initialFeeCollectorBalance, premium);

assertEq(expectedPremium, actualPremium);
}

function test_ValidatePaymasterAndPostOpWithPremium() external {
uint256 initialDappPaymasterBalance = 10 ether;
bicoPaymaster.depositFor{ value: initialDappPaymasterBalance }(DAPP_ACCOUNT.addr);

PackedUserOperation[] memory ops = new PackedUserOperation[](1);

uint48 validUntil = uint48(block.timestamp + 1 days);
uint48 validAfter = uint48(block.timestamp);

PackedUserOperation memory userOp = buildUserOpWithCalldata(ALICE, "", address(VALIDATOR_MODULE));

// Charge a 10% premium
bicoPaymaster.depositFor{ value: 10 ether }(DAPP_ACCOUNT.addr);
// 10% premium on gas cost
uint32 premium = 1e6 + 1e5;
userOp.paymasterAndData = generateAndSignPaymasterData(
userOp, PAYMASTER_SIGNER, bicoPaymaster, 3e6, 3e6, DAPP_ACCOUNT.addr, validUntil, validAfter, premium
);
userOp.signature = signUserOp(ALICE, userOp);

// Estimate paymaster gas limits
bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp);
(uint256 validationGasLimit, uint256 postopGasLimit) =
estimatePaymasterGasCosts(bicoPaymaster, userOp, userOpHash, 5e4);

// Ammend the userop to have new gas limits and signature
userOp.paymasterAndData = generateAndSignPaymasterData(
userOp,
PAYMASTER_SIGNER,
bicoPaymaster,
uint128(validationGasLimit),
uint128(postopGasLimit),
DAPP_ACCOUNT.addr,
validUntil,
validAfter,
premium
);
userOp.signature = signUserOp(ALICE, userOp);
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
(PackedUserOperation memory userOp, bytes32 userOpHash) = createUserOp(ALICE, bicoPaymaster, premium);
ops[0] = userOp;
userOpHash = ENTRYPOINT.getUserOpHash(userOp);

uint256 initialDappPaymasterBalance = bicoPaymaster.getBalance(DAPP_ACCOUNT.addr);
uint256 initialFeeCollectorBalance = bicoPaymaster.getBalance(PAYMASTER_FEE_COLLECTOR.addr);
initialDappPaymasterBalance = bicoPaymaster.getBalance(DAPP_ACCOUNT.addr);

// submit userops
vm.expectEmit(true, false, false, true, address(bicoPaymaster));
emit IBiconomySponsorshipPaymaster.PremiumCollected(DAPP_ACCOUNT.addr, 0);
vm.expectEmit(true, false, true, true, address(bicoPaymaster));
emit IBiconomySponsorshipPaymaster.GasBalanceDeducted(DAPP_ACCOUNT.addr, 0, userOpHash);
ENTRYPOINT.handleOps(ops, payable(BUNDLER.addr));

uint256 resultingDappPaymasterBalance = bicoPaymaster.getBalance(DAPP_ACCOUNT.addr);
uint256 resultingFeeCollectorPaymasterBalance = bicoPaymaster.getBalance(PAYMASTER_FEE_COLLECTOR.addr);

uint256 totalGasFeesCharged = initialDappPaymasterBalance - resultingDappPaymasterBalance;
uint256 premiumCollected = resultingFeeCollectorPaymasterBalance - initialFeeCollectorBalance;

uint256 expectedGasPayment = totalGasFeesCharged - premiumCollected;
uint256 expectedPremium = expectedGasPayment / 10;
(uint256 expectedPremium, uint256 actualPremium) =
getPremiums(bicoPaymaster, initialDappPaymasterBalance, initialFeeCollectorBalance, premium);

assertEq(premiumCollected, expectedPremium);
assertEq(expectedPremium, actualPremium);
}

function test_RevertIf_ValidatePaymasterUserOpWithIncorrectSignatureLength() external {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,59 +101,24 @@ contract TestFuzz_SponsorshipPaymasterWithPremium is NexusTestBase {
function testFuzz_ValidatePaymasterAndPostOpWithPremium(uint32 premium) external {
vm.assume(premium <= 2e6);
vm.assume(premium > 1e6);

uint256 initialDappPaymasterBalance = 10 ether;
bicoPaymaster.depositFor{ value: initialDappPaymasterBalance }(DAPP_ACCOUNT.addr);
bicoPaymaster.depositFor{ value: 10 ether }(DAPP_ACCOUNT.addr);

PackedUserOperation[] memory ops = new PackedUserOperation[](1);

uint48 validUntil = uint48(block.timestamp + 1 days);
uint48 validAfter = uint48(block.timestamp);

PackedUserOperation memory userOp = buildUserOpWithCalldata(ALICE, "", address(VALIDATOR_MODULE));

userOp.paymasterAndData = generateAndSignPaymasterData(
userOp, PAYMASTER_SIGNER, bicoPaymaster, 3e6, 3e6, DAPP_ACCOUNT.addr, validUntil, validAfter, premium
);
userOp.signature = signUserOp(ALICE, userOp);

// Estimate paymaster gas limits
bytes32 userOpHash = ENTRYPOINT.getUserOpHash(userOp);
(uint256 validationGasLimit, uint256 postopGasLimit) =
estimatePaymasterGasCosts(bicoPaymaster, userOp, userOpHash, 5e4);

// Ammend the userop to have new gas limits and signature
userOp.paymasterAndData = generateAndSignPaymasterData(
userOp,
PAYMASTER_SIGNER,
bicoPaymaster,
uint128(validationGasLimit),
uint128(postopGasLimit),
DAPP_ACCOUNT.addr,
validUntil,
validAfter,
premium
);
userOp.signature = signUserOp(ALICE, userOp);
(PackedUserOperation memory userOp, bytes32 userOpHash) = createUserOp(ALICE, bicoPaymaster, premium);
ops[0] = userOp;
userOpHash = ENTRYPOINT.getUserOpHash(userOp);

uint256 initialFeeCollectorBalance = bicoPaymaster.getBalance(PAYMASTER_FEE_COLLECTOR.addr);
initialDappPaymasterBalance = bicoPaymaster.getBalance(DAPP_ACCOUNT.addr);
uint256 initialDappPaymasterBalance = bicoPaymaster.getBalance(DAPP_ACCOUNT.addr);
vm.expectEmit(true, false, false, true, address(bicoPaymaster));
emit IBiconomySponsorshipPaymaster.PremiumCollected(DAPP_ACCOUNT.addr, 0);
vm.expectEmit(true, false, true, true, address(bicoPaymaster));
emit IBiconomySponsorshipPaymaster.GasBalanceDeducted(DAPP_ACCOUNT.addr, 0, userOpHash);
ENTRYPOINT.handleOps(ops, payable(BUNDLER.addr));

uint256 resultingDappPaymasterBalance = bicoPaymaster.getBalance(DAPP_ACCOUNT.addr);
uint256 resultingFeeCollectorPaymasterBalance = bicoPaymaster.getBalance(PAYMASTER_FEE_COLLECTOR.addr);

uint256 totalGasFeesCharged = initialDappPaymasterBalance - resultingDappPaymasterBalance;
(uint256 expectedPremium, uint256 actualPremium) =
getPremiums(bicoPaymaster, initialDappPaymasterBalance, initialFeeCollectorBalance, premium);

uint256 premiumCollected = resultingFeeCollectorPaymasterBalance - initialFeeCollectorBalance;
uint256 expectedPremium = totalGasFeesCharged - ((totalGasFeesCharged * 1e6) / premium);

assertEq(premiumCollected, expectedPremium);
assertEq(expectedPremium, actualPremium);
}

}

0 comments on commit 5ad5619

Please sign in to comment.