diff --git a/remappings.txt b/remappings.txt index 0d65b04..b856161 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,3 +1,4 @@ @openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/ @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ @solady/=lib/solady/src/ +@socket/=lib/socket-DL/contracts/ \ No newline at end of file diff --git a/src/settlement/UserOpSettlement.sol b/src/settlement/UserOpSettlement.sol index 72b8659..f56633c 100644 --- a/src/settlement/UserOpSettlement.sol +++ b/src/settlement/UserOpSettlement.sol @@ -4,28 +4,50 @@ pragma solidity ^0.8.0; import {IPaymasterVerifier} from "../interfaces/IPaymasterVerifier.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {ISocket} from "@socket/interfaces/ISocket.sol"; contract UserOpSettlement is UUPSUpgradeable, OwnableUpgradeable { + ISocket public immutable socket; + uint256 public minMsgGasLimit; address public paymaster; + error NoSocketFee(); + error NotSocket(); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* STORAGE */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /// @notice Mapping: userOpHash => SponsorToken[] to store the sponsor tokens. mapping(bytes32 => IPaymasterVerifier.SponsorToken[]) public userOpWithSponsorTokens; - constructor() { + constructor(address _socket) { + socket = ISocket(_socket); _disableInitializers(); } - function initialize(address _owner, address _paymaster) public initializer { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* ADMIN FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + modifier onlyPaymaster() { + require(msg.sender == paymaster, "Only paymaster can call this function"); + _; + } + + function initialize(address _owner, address _paymaster, uint256 _minMsgGasLimit) public initializer { __Ownable_init(_owner); paymaster = _paymaster; + + // gas limit for the outbound call + minMsgGasLimit = _minMsgGasLimit; } function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} - modifier onlyPaymaster() { - require(msg.sender == paymaster, "Only paymaster can call this function"); - _; - } + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PAYMASTER FUNCTIONS */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @notice Add the sponsor tokens to the userOpHash. function push(bytes32 userOpHash, IPaymasterVerifier.SponsorToken[] calldata sponsorTokens) public onlyPaymaster { @@ -40,4 +62,26 @@ contract UserOpSettlement is UUPSUpgradeable, OwnableUpgradeable { // delete userOpWithSponsorTokens[userOpHashes[i]]; // } // } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* SOCKET */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + function connect(uint32 remoteChainSlug, address remotePlug, address switchboard) public onlyOwner { + socket.connect(remoteChainSlug, remotePlug, switchboard, switchboard); + } + + function _outbound(uint32 targetChain, bytes32 executionParams, bytes32 transmissionParams, bytes memory payload) + private + { + uint256 fee = socket.getMinFees( + minMsgGasLimit, uint256(payload.length), executionParams, transmissionParams, targetChain, address(this) + ); + + // This UserOpSettlement contract must have enouh native token + // to pay for the outbound call !!!! + + if (address(this).balance < fee) revert NoSocketFee(); + socket.outbound{value: fee}(targetChain, minMsgGasLimit, executionParams, transmissionParams, payload); + } } diff --git a/test/CABPaymater.t.sol b/test/CABPaymater.t.sol index 146d026..462669a 100644 --- a/test/CABPaymater.t.sol +++ b/test/CABPaymater.t.sol @@ -35,11 +35,13 @@ contract CABPaymasterTest is Test { uint256 public verifyingSignerPrivateKey; address public owner; address public rekt; + address public socket; function setUp() public { entryPoint = new EntryPoint(); owner = address(1); rekt = address(0x9590Ed0C18190a310f4e93CAccc4CC17270bED40); + socket = address(0x07e11D1A1543B0D0b91684eb741d1ab7D51ae237); verifyingSignerPrivateKey = uint256(keccak256(abi.encodePacked("VERIFIYING_SIGNER"))); verifyingSignerAddress = vm.addr(verifyingSignerPrivateKey); @@ -68,9 +70,9 @@ contract CABPaymasterTest is Test { ) ); invoiceManager.initialize(owner, IVaultManager(address(vaultManager))); - settlement = UserOpSettlement(payable(new UpgradeableOpenfortProxy(address(new UserOpSettlement()), ""))); + settlement = UserOpSettlement(payable(new UpgradeableOpenfortProxy(address(new UserOpSettlement(socket)), ""))); paymaster = new CABPaymaster(entryPoint, invoiceManager, verifyingSignerAddress, owner, address(settlement)); - settlement.initialize(owner, address(paymaster)); + settlement.initialize(owner, address(paymaster), 1e3); mockERC20.mint(address(paymaster), PAYMSTER_BASE_MOCK_ERC20_BALANCE);