From 3ea69d2b7f659727b5d3a059ad43129af94bd4ea Mon Sep 17 00:00:00 2001 From: Anna Carroll Date: Fri, 19 Jul 2024 15:47:50 +0100 Subject: [PATCH] refactor: generate witness as public field --- src/Orders.sol | 8 +++++-- src/Passage.sol | 4 ++-- src/permit2/UsesPermit2.sol | 48 ++++++++++++++++++++++++------------- test/Passage.t.sol | 2 -- 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/Orders.sol b/src/Orders.sol index 838d5d8..c982875 100644 --- a/src/Orders.sol +++ b/src/Orders.sol @@ -50,7 +50,9 @@ abstract contract OrderDestination is IOrders, OrdersPermit2 { /// @custom:emits Filled function fillPermit2(Output[] memory outputs, OrdersPermit2.Permit2Batch calldata permit2) external { // transfer all tokens to the Output recipients via permit2 (includes check on nonce & deadline) - _permitWitnessTransferFrom(outputs, _fillTransferDetails(outputs, permit2.permit.permitted), permit2); + _permitWitnessTransferFrom( + outputsWitness(outputs), _fillTransferDetails(outputs, permit2.permit.permitted), permit2 + ); // emit emit Filled(outputs); @@ -123,7 +125,9 @@ abstract contract OrderOrigin is IOrders, OrdersPermit2 { OrdersPermit2.Permit2Batch calldata permit2 ) external { // transfer all tokens to the tokenRecipient via permit2 (includes check on nonce & deadline) - _permitWitnessTransferFrom(outputs, _initiateTransferDetails(tokenRecipient, permit2.permit.permitted), permit2); + _permitWitnessTransferFrom( + outputsWitness(outputs), _initiateTransferDetails(tokenRecipient, permit2.permit.permitted), permit2 + ); // emit emit Order(permit2.permit.deadline, _inputs(permit2.permit.permitted), outputs); diff --git a/src/Passage.sol b/src/Passage.sol index c8ed2d1..fc1d1a3 100644 --- a/src/Passage.sol +++ b/src/Passage.sol @@ -109,7 +109,7 @@ contract Passage is PassagePermit2 { public { // transfer tokens to this contract via permit2 - _permitWitnessTransferFrom(_enterWitness(rollupChainId, rollupRecipient), true, permit2); + _permitWitnessTransferFrom(enterWitness(rollupChainId, rollupRecipient), permit2); // check and emit _enterToken(rollupChainId, rollupRecipient, permit2.permit.permitted.token, permit2.permit.permitted.amount); } @@ -197,7 +197,7 @@ contract RollupPassage is PassagePermit2 { /// @custom:emits ExitToken function exitTokenPermit2(address hostRecipient, PassagePermit2.Permit2 calldata permit2) public { // transfer tokens to this contract - _permitWitnessTransferFrom(_exitWitness(hostRecipient), false, permit2); + _permitWitnessTransferFrom(exitWitness(hostRecipient), permit2); // burn and emit _exitToken(hostRecipient, permit2.permit.permitted.token, permit2.permit.permitted.amount); } diff --git a/src/permit2/UsesPermit2.sol b/src/permit2/UsesPermit2.sol index b4edad6..9b4d141 100644 --- a/src/permit2/UsesPermit2.sol +++ b/src/permit2/UsesPermit2.sol @@ -5,6 +5,12 @@ import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol" import {IOrders} from "../interfaces/IOrders.sol"; abstract contract UsesPermit2 { + /// @notice Struct to hold the pre-hashed witness field and the witness type string. + struct Witness { + bytes32 witnessHash; + string witnessTypeString; + } + /// @notice The Permit2 contract address. address immutable permit2Contract; @@ -33,11 +39,11 @@ abstract contract OrdersPermit2 is UsesPermit2 { error OutputMismatch(); /// @notice Transfer a batch of tokens using permit2. - /// @param outputs - the Outputs for the witness field. + /// @param _witness - the hashed witness and its typestring. /// @param transferDetails - the TokenPermissions for the transfer, generated based on the use-case (see `_initiateTransferDetails` and `_fillTransferDetails`). /// @param permit2 - the Permit2Batch information. function _permitWitnessTransferFrom( - IOrders.Output[] memory outputs, + Witness memory _witness, ISignatureTransfer.SignatureTransferDetails[] memory transferDetails, Permit2Batch calldata permit2 ) internal { @@ -45,22 +51,23 @@ abstract contract OrdersPermit2 is UsesPermit2 { permit2.permit, transferDetails, permit2.owner, - _witness(outputs), - _OUTPUT_WITNESS_TYPESTRING, + _witness.witnessHash, + _witness.witnessTypeString, permit2.signature ); } /// @notice Encode the Output array according to EIP-712 for use as a permit2 witness. /// @param outputs - the Outputs to encode. - /// @return witness - the encoded witness field. - function _witness(IOrders.Output[] memory outputs) internal pure returns (bytes32 witness) { + /// @return _witness - the encoded witness field. + function outputsWitness(IOrders.Output[] memory outputs) public pure returns (Witness memory _witness) { uint256 num = outputs.length; bytes32[] memory hashes = new bytes32[](num); for (uint256 i = 0; i < num; ++i) { hashes[i] = keccak256(abi.encode(_OUTPUT_TYPEHASH, outputs[i])); } - witness = keccak256(abi.encodePacked(hashes)); + _witness.witnessHash = keccak256(abi.encodePacked(hashes)); + _witness.witnessTypeString = _OUTPUT_WITNESS_TYPESTRING; } /// @notice transform Output and TokenPermissions structs to TransferDetails structs, for passing to permit2. @@ -145,29 +152,36 @@ abstract contract PassagePermit2 is UsesPermit2 { } /// @notice Transfer tokens using permit2. - /// @param witness - the pre-hashed witness field. + /// @param _witness - the hashed witness and its typestring. /// @param permit2 - the Permit2 information. - function _permitWitnessTransferFrom(bytes32 witness, bool isEnter, Permit2 calldata permit2) internal { + function _permitWitnessTransferFrom(Witness memory _witness, Permit2 calldata permit2) internal { ISignatureTransfer(permit2Contract).permitWitnessTransferFrom( permit2.permit, _passageTransferDetails(permit2.permit.permitted), permit2.owner, - witness, - isEnter ? _ENTER_WITNESS_TYPESTRING : _EXIT_WITNESS_TYPESTRING, + _witness.witnessHash, + _witness.witnessTypeString, permit2.signature ); } /// @notice Encode & hash the rollupChainId and rollupRecipient for use as a permit2 witness. - /// @return witness - the encoded witness field. - function _enterWitness(uint256 rollupChainId, address rollupRecipient) internal pure returns (bytes32 witness) { - witness = keccak256(abi.encode(_ENTER_WITNESS_TYPEHASH, EnterWitness(rollupChainId, rollupRecipient))); + /// @return _witness - the hashed witness and its typestring. + function enterWitness(uint256 rollupChainId, address rollupRecipient) + public + pure + returns (Witness memory _witness) + { + _witness.witnessHash = + keccak256(abi.encode(_ENTER_WITNESS_TYPEHASH, EnterWitness(rollupChainId, rollupRecipient))); + _witness.witnessTypeString = _ENTER_WITNESS_TYPESTRING; } /// @notice Hash the hostRecipient for use as a permit2 witness. - /// @return witness - the encoded witness field. - function _exitWitness(address hostRecipient) internal pure returns (bytes32 witness) { - witness = keccak256(abi.encode(_EXIT_WITNESS_TYPEHASH, ExitWitness(hostRecipient))); + /// @return _witness - the hashed witness and its typestring. + function exitWitness(address hostRecipient) public pure returns (Witness memory _witness) { + _witness.witnessHash = keccak256(abi.encode(_EXIT_WITNESS_TYPEHASH, ExitWitness(hostRecipient))); + _witness.witnessTypeString = _EXIT_WITNESS_TYPESTRING; } /// @notice transform TokenPermissions to TransferDetails, for passing to permit2. diff --git a/test/Passage.t.sol b/test/Passage.t.sol index 1c682b0..3f61c02 100644 --- a/test/Passage.t.sol +++ b/test/Passage.t.sol @@ -21,8 +21,6 @@ contract PassageTest is Test { uint256 gas = 10_000_000; uint256 maxFeePerGas = 50; - uint256 tokenAdminKey = 123; - event Enter(uint256 indexed rollupChainId, address indexed rollupRecipient, uint256 amount); event EnterToken(