Skip to content

Commit

Permalink
demo: add permit flow
Browse files Browse the repository at this point in the history
  • Loading branch information
anna-carroll committed Jul 12, 2024
1 parent 81e9690 commit 5e36146
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 27 deletions.
44 changes: 22 additions & 22 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
OrdersTest:test_fill_ERC20() (gas: 70364)
OrdersTest:test_fill_ETH() (gas: 68414)
OrdersTest:test_fill_both() (gas: 166580)
OrdersTest:test_fill_multiETH() (gas: 131926)
OrdersTest:test_fill_underflowETH() (gas: 115281)
OrdersTest:test_initiate_ERC20() (gas: 81435)
OrdersTest:test_initiate_ETH() (gas: 44949)
OrdersTest:test_initiate_both() (gas: 118677)
OrdersTest:test_initiate_multiERC20() (gas: 688417)
OrdersTest:test_initiate_multiETH() (gas: 75304)
OrdersTest:test_onlyBuilder() (gas: 12815)
OrdersTest:test_orderExpired() (gas: 27956)
OrdersTest:test_sweepERC20() (gas: 60402)
OrdersTest:test_sweepETH() (gas: 81940)
OrdersTest:test_underflowETH() (gas: 63528)
PassageTest:test_configureEnter() (gas: 82311)
OrdersTest:test_fill_ERC20() (gas: 70408)
OrdersTest:test_fill_ETH() (gas: 68458)
OrdersTest:test_fill_both() (gas: 166624)
OrdersTest:test_fill_multiETH() (gas: 131970)
OrdersTest:test_fill_underflowETH() (gas: 115325)
OrdersTest:test_initiate_ERC20() (gas: 81505)
OrdersTest:test_initiate_ETH() (gas: 45019)
OrdersTest:test_initiate_both() (gas: 118738)
OrdersTest:test_initiate_multiERC20() (gas: 688478)
OrdersTest:test_initiate_multiETH() (gas: 75365)
OrdersTest:test_onlyBuilder() (gas: 12859)
OrdersTest:test_orderExpired() (gas: 28026)
OrdersTest:test_sweepERC20() (gas: 60446)
OrdersTest:test_sweepETH() (gas: 82054)
OrdersTest:test_underflowETH() (gas: 63589)
PassageTest:test_configureEnter() (gas: 82357)
PassageTest:test_disallowedEnter() (gas: 17916)
PassageTest:test_enter() (gas: 25563)
PassageTest:test_enter() (gas: 25541)
PassageTest:test_enterToken() (gas: 64332)
PassageTest:test_enterToken_defaultChain() (gas: 62915)
PassageTest:test_enterTransact() (gas: 60890)
PassageTest:test_enter_defaultChain() (gas: 24033)
PassageTest:test_enterTransact() (gas: 60936)
PassageTest:test_enter_defaultChain() (gas: 24011)
PassageTest:test_fallback() (gas: 21534)
PassageTest:test_onlyTokenAdmin() (gas: 16926)
PassageTest:test_onlyTokenAdmin() (gas: 16927)
PassageTest:test_receive() (gas: 21384)
PassageTest:test_setUp() (gas: 16968)
PassageTest:test_setUp() (gas: 16991)
PassageTest:test_transact() (gas: 58562)
PassageTest:test_transact_defaultChain() (gas: 57475)
PassageTest:test_withdraw() (gas: 59033)
PassageTest:test_withdraw() (gas: 59011)
ZenithTest:test_addSequencer() (gas: 88121)
ZenithTest:test_badSignature() (gas: 37241)
ZenithTest:test_incorrectHostBlock() (gas: 35086)
Expand Down
26 changes: 22 additions & 4 deletions src/Orders.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.24;

import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {Permit, PermitLib} from "./Permit.sol";

/// @notice Tokens sent by the swapper as inputs to the order
/// @dev From ERC-7683
Expand All @@ -28,7 +29,7 @@ struct Output {
}

/// @notice Contract capable of processing fulfillment of intent-based Orders.
abstract contract OrderDestination {
abstract contract OrderDestination is PermitLib {
/// @notice Emitted when Order Outputs are sent to their recipients.
/// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
event Filled(Output[] outputs);
Expand All @@ -39,7 +40,7 @@ abstract contract OrderDestination {
/// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
/// @param outputs - The Outputs to be transferred.
/// @custom:emits Filled
function fill(Output[] memory outputs) external payable {
function fill(Output[] memory outputs) public payable {
// transfer outputs
uint256 value = msg.value;
for (uint256 i; i < outputs.length; i++) {
Expand All @@ -54,10 +55,17 @@ abstract contract OrderDestination {
// emit
emit Filled(outputs);
}

function fillPermit(Output[] memory outputs, Permit[] memory permits) external payable {
// first, execute token permissions to set token allowance
_permit(permits);
// then, fill orders
fill(outputs);
}
}

/// @notice Contract capable of registering initiation of intent-based Orders.
abstract contract OrderOrigin {
abstract contract OrderOrigin is PermitLib {
/// @notice Thrown when an Order is submitted with a deadline that has passed.
error OrderExpired();

Expand Down Expand Up @@ -86,7 +94,7 @@ abstract contract OrderOrigin {
/// @param outputs - The token amounts that must be received on their target chain(s) in order for the Order to be executed.
/// @custom:reverts OrderExpired if the deadline has passed.
/// @custom:emits Order if the transaction mines.
function initiate(uint256 deadline, Input[] memory inputs, Output[] memory outputs) external payable {
function initiate(uint256 deadline, Input[] memory inputs, Output[] memory outputs) public payable {
// check that the deadline hasn't passed
if (block.timestamp > deadline) revert OrderExpired();

Expand All @@ -97,6 +105,16 @@ abstract contract OrderOrigin {
emit Order(deadline, inputs, outputs);
}

function initiatePermit(Permit[] memory permits, uint256 deadline, Input[] memory inputs, Output[] memory outputs)
external
payable
{
// first, execute token permissions to set token allowance
_permit(permits);
// then, initiate the Order
initiate(deadline, inputs, outputs);
}

/// @notice Transfer the Order inputs to this contract, where they can be collected by the Order filler.
function _transferInputs(Input[] memory inputs) internal {
uint256 value = msg.value;
Expand Down
15 changes: 14 additions & 1 deletion src/Passage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
pragma solidity ^0.8.24;

import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {Permit, PermitLib} from "./Permit.sol";

/// @notice A contract deployed to Host chain that allows tokens to enter the rollup,
/// and enables Builders to fulfill requests to exchange tokens on the Rollup for tokens on the Host.
contract Passage {
contract Passage is PermitLib {
/// @notice The chainId of rollup that Ether will be sent to by default when entering the rollup via fallback() or receive().
uint256 public immutable defaultRollupChainId;

Expand Down Expand Up @@ -106,6 +107,18 @@ contract Passage {
enterToken(defaultRollupChainId, rollupRecipient, token, amount);
}

/// @notice Allows ERC20 tokens to enter the rollup with a permit message.
function enterTokenPermit(
uint256 rollupChainId,
address rollupRecipient,
address token,
uint256 amount,
Permit memory permit
) external {
_permit(permit);
enterToken(rollupChainId, rollupRecipient, token, amount);
}

/// @notice Allows a special transaction to be sent to the rollup with sender == L1 msg.sender.
/// @dev Transaction is processed after normal rollup block execution.
/// @dev See `enterTransact` for docs.
Expand Down
29 changes: 29 additions & 0 deletions src/Permit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import {IERC20Permit} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol";

struct Permit {
address token;
address owner;
address spender;
uint256 value;
uint256 deadline;
uint8 v;
bytes32 r;
bytes32 s;
}

abstract contract PermitLib {
function _permit(Permit memory permit) internal {
IERC20Permit(permit.token).permit(
permit.owner, permit.spender, permit.value, permit.deadline, permit.v, permit.r, permit.s
);
}

function _permit(Permit[] memory permits) internal {
for (uint256 i; i < permits.length; i++) {
_permit(permits[i]);
}
}
}

0 comments on commit 5e36146

Please sign in to comment.