Skip to content

Commit

Permalink
E2E tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Da-Colon committed Jan 1, 2025
1 parent ab75c04 commit ba285ac
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 22 deletions.
23 changes: 1 addition & 22 deletions contracts/src/ErrantryClientSmartAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ contract ErrantryClientSmartAccount is SimpleAccount, OnlyOracle {
{}
/* >>>>>>>> general external functions <<<<<<< */

function payErrands(IErrandManager errandManager) external {
function payErrands(IErrandManager errandManager) external onlyOracle {
require(errandManager.getClientSmartAccountAddress() == address(this), ErrandManagerMismatch());
IErrandManager.Errand[] memory errands = errandManager.getUnPaidErrands();

Expand All @@ -41,27 +41,6 @@ contract ErrantryClientSmartAccount is SimpleAccount, OnlyOracle {
}
}

function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash)
internal
override
returns (uint256 validationData)
{
bytes memory _callData = userOp.callData;
// Extract the function selector from the first 4 bytes of callData
bytes4 functionSelector;
assembly {
functionSelector := calldataload(add(_callData, 0x20)) // Skip the 32-byte length prefix of the bytes array
}

if (functionSelector == this.payErrands.selector && msg.sender == TRUSTED_ORACLE) {
// Return validation success without further signature checks
return SIG_VALIDATION_SUCCESS;
}

// For other functions, proceed with the default signature validation
return super._validateSignature(userOp, userOpHash);
}

/* >>>>>>>> internal functions <<<<<<< */
function _checkErrandFundBalance(address token, uint256 requiredAmount) internal view returns (bool) {
return IERC20(token).balanceOf(address(this)) >= requiredAmount;
Expand Down
85 changes: 85 additions & 0 deletions contracts/test/ErrantryE2E.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "./mocks/MockEntryPoint.sol";
import {MockERC20} from "./mocks/MockERC20.sol";
import {Errantry} from "../src/Errantry.sol";
import {IErrantry} from "../src/interfaces/IErrantry.sol";
import {IErrandManager} from "../src/interfaces/IErrandManager.sol";
import {ErrantryClientSmartAccount} from "../src/ErrantryClientSmartAccount.sol";
import "forge-std/Test.sol";

contract ErrantryE2ETest is Test {
// Contracts
MockEntryPoint private mockEntryPoint;
MockERC20 private mockToken;
Errantry private errantry;

// Addresses
address private oracle = address(0xACE0); // Trusted Oracle
address private client = vm.addr(1);
address private runner = vm.addr(2);

// Test Data
uint256 private expires = block.timestamp + 1 days;
uint256 private errandAmount = 1000;

function setUp() public {
// Deploy MockEntryPoint and MockToken
mockEntryPoint = new MockEntryPoint();
mockToken = new MockERC20("MockToken", "MKT");

// Deploy Errantry contract
errantry = new Errantry(mockEntryPoint, oracle);

// Register Client
vm.prank(client);
errantry.registerNewClient(client);
}

function testEndToEndFlow() public {
// Step 1: Post a new errand
vm.startPrank(oracle);
IErrantry.PostNewErrandParams memory params = IErrantry.PostNewErrandParams({
client: client,
expires: expires,
tokenAddress: address(mockToken),
amount: errandAmount
});
errantry.postNewErrand(params);

// Step 2: Assign a runner
errantry.updateErrandRunner(0, client, runner);

// Step 3: Mark the errand as complete
errantry.markErrandAsComplete(0, client);
vm.stopPrank();

// Step 4: Simulate user operation for payment
address errandManagerAddr = errantry.getErrandManagerAddress(client);
IErrandManager errandManager = IErrandManager(errandManagerAddr);

vm.startPrank(oracle);
address smartAccount = errandManager.getClientSmartAccountAddress();
ErrantryClientSmartAccount smartAccountContract = ErrantryClientSmartAccount(payable(smartAccount));

// Mint tokens to the client for payments
mockToken.mint(smartAccount, errandAmount * 10);

// Mark the errand as paid
smartAccountContract.payErrands(errandManager);

vm.stopPrank();

// Step 5: Verify payment was successful
uint256 runnerBalance = mockToken.balanceOf(runner);
assertEq(runnerBalance, errandAmount, "Runner should receive the payment");

IErrandManager.Errand memory errand = errandManager.getErrand(0);
assertEq(errand.status, 3, "Errand status should indicate 'paid'");

// Step 6: Verify client's balance decreased
uint256 clientBalance = mockToken.balanceOf(smartAccount);
assertEq(clientBalance, errandAmount * 9, "Client's balance should decrease by errand amount");
}
}
30 changes: 30 additions & 0 deletions contracts/test/mocks/MockERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

/**
* @title MockERC20
* @dev A simple ERC20 token implementation for testing purposes.
*/
contract MockERC20 is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}

/**
* @dev Mints `amount` tokens to `account`.
* @param account The account to mint tokens to.
* @param amount The amount of tokens to mint.
*/
function mint(address account, uint256 amount) external {
_mint(account, amount);
}

/**
* @dev Burns `amount` tokens from `account`.
* @param account The account to burn tokens from.
* @param amount The amount of tokens to burn.
*/
function burn(address account, uint256 amount) external {
_burn(account, amount);
}
}

0 comments on commit ba285ac

Please sign in to comment.