diff --git a/.forge-snapshots/batchTransferFrom.snap b/.forge-snapshots/batchTransferFrom.snap
index 12330bfb..2cdbff48 100644
--- a/.forge-snapshots/batchTransferFrom.snap
+++ b/.forge-snapshots/batchTransferFrom.snap
@@ -1 +1 @@
-61797
\ No newline at end of file
+40275
\ No newline at end of file
diff --git a/.forge-snapshots/batchTransferFromMultiToken.snap b/.forge-snapshots/batchTransferFromMultiToken.snap
index 6372f872..d45c5234 100644
--- a/.forge-snapshots/batchTransferFromMultiToken.snap
+++ b/.forge-snapshots/batchTransferFromMultiToken.snap
@@ -1 +1 @@
-81786
\ No newline at end of file
+60132
\ No newline at end of file
diff --git a/.forge-snapshots/lockdown.snap b/.forge-snapshots/lockdown.snap
index a193479b..37b36262 100644
--- a/.forge-snapshots/lockdown.snap
+++ b/.forge-snapshots/lockdown.snap
@@ -1 +1 @@
-28435
\ No newline at end of file
+6450
\ No newline at end of file
diff --git a/.forge-snapshots/permit2 + transferFrom2 with WETH9's mainnet address.snap b/.forge-snapshots/permit2 + transferFrom2 with WETH9's mainnet address.snap
index 95b3b96c..85befeb2 100644
--- a/.forge-snapshots/permit2 + transferFrom2 with WETH9's mainnet address.snap	
+++ b/.forge-snapshots/permit2 + transferFrom2 with WETH9's mainnet address.snap	
@@ -1 +1 @@
-60346
\ No newline at end of file
+60343
\ No newline at end of file
diff --git a/.forge-snapshots/permit2 + transferFrom2 with a non EIP-2612 native token.snap b/.forge-snapshots/permit2 + transferFrom2 with a non EIP-2612 native token.snap
index 70b916f2..f6fd21a4 100644
--- a/.forge-snapshots/permit2 + transferFrom2 with a non EIP-2612 native token.snap	
+++ b/.forge-snapshots/permit2 + transferFrom2 with a non EIP-2612 native token.snap	
@@ -1 +1 @@
-60811
\ No newline at end of file
+60784
\ No newline at end of file
diff --git a/.forge-snapshots/permit2 + transferFrom2 with an EIP-2612 native token.snap b/.forge-snapshots/permit2 + transferFrom2 with an EIP-2612 native token.snap
index ac024b17..e38eab09 100644
--- a/.forge-snapshots/permit2 + transferFrom2 with an EIP-2612 native token.snap	
+++ b/.forge-snapshots/permit2 + transferFrom2 with an EIP-2612 native token.snap	
@@ -1 +1 @@
-46296
\ No newline at end of file
+46230
\ No newline at end of file
diff --git a/.forge-snapshots/permitBatchCleanWrite.snap b/.forge-snapshots/permitBatchCleanWrite.snap
index ff36c94f..3d6111c0 100644
--- a/.forge-snapshots/permitBatchCleanWrite.snap
+++ b/.forge-snapshots/permitBatchCleanWrite.snap
@@ -1 +1 @@
-91924
\ No newline at end of file
+69636
\ No newline at end of file
diff --git a/.forge-snapshots/permitBatchDirtyWrite.snap b/.forge-snapshots/permitBatchDirtyWrite.snap
index 2020125e..89b51398 100644
--- a/.forge-snapshots/permitBatchDirtyWrite.snap
+++ b/.forge-snapshots/permitBatchDirtyWrite.snap
@@ -1 +1 @@
-57724
\ No newline at end of file
+35436
\ No newline at end of file
diff --git a/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap b/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap
index bd650401..cad71026 100644
--- a/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap
+++ b/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap
@@ -1 +1 @@
-143387
\ No newline at end of file
+120840
\ No newline at end of file
diff --git a/.forge-snapshots/permitBatchTransferFromSingleToken.snap b/.forge-snapshots/permitBatchTransferFromSingleToken.snap
index c1642c97..8e91e0e8 100644
--- a/.forge-snapshots/permitBatchTransferFromSingleToken.snap
+++ b/.forge-snapshots/permitBatchTransferFromSingleToken.snap
@@ -1 +1 @@
-88867
\ No newline at end of file
+66552
\ No newline at end of file
diff --git a/.forge-snapshots/permitCleanWrite.snap b/.forge-snapshots/permitCleanWrite.snap
index c49bc2ab..2bafb98d 100644
--- a/.forge-snapshots/permitCleanWrite.snap
+++ b/.forge-snapshots/permitCleanWrite.snap
@@ -1 +1 @@
-63119
\ No newline at end of file
+40904
\ No newline at end of file
diff --git a/.forge-snapshots/permitCompactSig.snap b/.forge-snapshots/permitCompactSig.snap
index eb882987..cb2734ac 100644
--- a/.forge-snapshots/permitCompactSig.snap
+++ b/.forge-snapshots/permitCompactSig.snap
@@ -1 +1 @@
-63094
\ No newline at end of file
+40941
\ No newline at end of file
diff --git a/.forge-snapshots/permitDirtyNonce.snap b/.forge-snapshots/permitDirtyNonce.snap
index a909d364..07272edf 100644
--- a/.forge-snapshots/permitDirtyNonce.snap
+++ b/.forge-snapshots/permitDirtyNonce.snap
@@ -1 +1 @@
-44014
\ No newline at end of file
+21799
\ No newline at end of file
diff --git a/.forge-snapshots/permitDirtyWrite.snap b/.forge-snapshots/permitDirtyWrite.snap
index 451c9a87..416dea90 100644
--- a/.forge-snapshots/permitDirtyWrite.snap
+++ b/.forge-snapshots/permitDirtyWrite.snap
@@ -1 +1 @@
-46019
\ No newline at end of file
+23804
\ No newline at end of file
diff --git a/.forge-snapshots/permitInvalidSigner.snap b/.forge-snapshots/permitInvalidSigner.snap
index 73ab357b..6a30942d 100644
--- a/.forge-snapshots/permitInvalidSigner.snap
+++ b/.forge-snapshots/permitInvalidSigner.snap
@@ -1 +1 @@
-40301
\ No newline at end of file
+18168
\ No newline at end of file
diff --git a/.forge-snapshots/permitSetMaxAllowanceCleanWrite.snap b/.forge-snapshots/permitSetMaxAllowanceCleanWrite.snap
index 6e633733..007bfffc 100644
--- a/.forge-snapshots/permitSetMaxAllowanceCleanWrite.snap
+++ b/.forge-snapshots/permitSetMaxAllowanceCleanWrite.snap
@@ -1 +1 @@
-61114
\ No newline at end of file
+38899
\ No newline at end of file
diff --git a/.forge-snapshots/permitSetMaxAllowanceDirtyWrite.snap b/.forge-snapshots/permitSetMaxAllowanceDirtyWrite.snap
index a909d364..07272edf 100644
--- a/.forge-snapshots/permitSetMaxAllowanceDirtyWrite.snap
+++ b/.forge-snapshots/permitSetMaxAllowanceDirtyWrite.snap
@@ -1 +1 @@
-44014
\ No newline at end of file
+21799
\ No newline at end of file
diff --git a/.forge-snapshots/permitSignatureExpired.snap b/.forge-snapshots/permitSignatureExpired.snap
index 309c6d2b..5e8d0217 100644
--- a/.forge-snapshots/permitSignatureExpired.snap
+++ b/.forge-snapshots/permitSignatureExpired.snap
@@ -1 +1 @@
-31700
\ No newline at end of file
+9332
\ No newline at end of file
diff --git a/.forge-snapshots/permitTransferFromBatchTypedWitness.snap b/.forge-snapshots/permitTransferFromBatchTypedWitness.snap
index 3adcc82d..3182fecf 100644
--- a/.forge-snapshots/permitTransferFromBatchTypedWitness.snap
+++ b/.forge-snapshots/permitTransferFromBatchTypedWitness.snap
@@ -1 +1 @@
-120325
\ No newline at end of file
+97318
\ No newline at end of file
diff --git a/.forge-snapshots/permitTransferFromCompactSig.snap b/.forge-snapshots/permitTransferFromCompactSig.snap
index 3214529f..56747705 100644
--- a/.forge-snapshots/permitTransferFromCompactSig.snap
+++ b/.forge-snapshots/permitTransferFromCompactSig.snap
@@ -1 +1 @@
-86066
\ No newline at end of file
+63987
\ No newline at end of file
diff --git a/.forge-snapshots/permitTransferFromSingleToken.snap b/.forge-snapshots/permitTransferFromSingleToken.snap
index 8c739819..c64559d7 100644
--- a/.forge-snapshots/permitTransferFromSingleToken.snap
+++ b/.forge-snapshots/permitTransferFromSingleToken.snap
@@ -1 +1 @@
-86092
\ No newline at end of file
+63951
\ No newline at end of file
diff --git a/.forge-snapshots/permitTransferFromTypedWitness.snap b/.forge-snapshots/permitTransferFromTypedWitness.snap
index bf396ab1..4b3b26e6 100644
--- a/.forge-snapshots/permitTransferFromTypedWitness.snap
+++ b/.forge-snapshots/permitTransferFromTypedWitness.snap
@@ -1 +1 @@
-87817
\ No newline at end of file
+65078
\ No newline at end of file
diff --git a/.forge-snapshots/safePermit + safeTransferFrom with an EIP-2612 native token.snap b/.forge-snapshots/safePermit + safeTransferFrom with an EIP-2612 native token.snap
index 5424434f..ab4c2cae 100644
--- a/.forge-snapshots/safePermit + safeTransferFrom with an EIP-2612 native token.snap	
+++ b/.forge-snapshots/safePermit + safeTransferFrom with an EIP-2612 native token.snap	
@@ -1 +1 @@
-48268
\ No newline at end of file
+48296
\ No newline at end of file
diff --git a/.forge-snapshots/simplePermit2 + transferFrom2 with a non EIP-2612 native token.snap b/.forge-snapshots/simplePermit2 + transferFrom2 with a non EIP-2612 native token.snap
index 70b916f2..f6fd21a4 100644
--- a/.forge-snapshots/simplePermit2 + transferFrom2 with a non EIP-2612 native token.snap	
+++ b/.forge-snapshots/simplePermit2 + transferFrom2 with a non EIP-2612 native token.snap	
@@ -1 +1 @@
-60811
\ No newline at end of file
+60784
\ No newline at end of file
diff --git a/.forge-snapshots/single recipient 2 tokens.snap b/.forge-snapshots/single recipient 2 tokens.snap
index 37c51f05..95f589ba 100644
--- a/.forge-snapshots/single recipient 2 tokens.snap	
+++ b/.forge-snapshots/single recipient 2 tokens.snap	
@@ -1 +1 @@
-118525
\ No newline at end of file
+96094
\ No newline at end of file
diff --git a/.forge-snapshots/single recipient many tokens.snap b/.forge-snapshots/single recipient many tokens.snap
index 770e7a83..d39883c7 100644
--- a/.forge-snapshots/single recipient many tokens.snap	
+++ b/.forge-snapshots/single recipient many tokens.snap	
@@ -1 +1 @@
-133544
\ No newline at end of file
+110164
\ No newline at end of file
diff --git a/.forge-snapshots/transferFrom with different owners.snap b/.forge-snapshots/transferFrom with different owners.snap
index 26fba36e..dfe2ef6f 100644
--- a/.forge-snapshots/transferFrom with different owners.snap	
+++ b/.forge-snapshots/transferFrom with different owners.snap	
@@ -1 +1 @@
-61886
\ No newline at end of file
+40232
\ No newline at end of file
diff --git a/.forge-snapshots/transferFrom.snap b/.forge-snapshots/transferFrom.snap
index ebbbd605..3a11432c 100644
--- a/.forge-snapshots/transferFrom.snap
+++ b/.forge-snapshots/transferFrom.snap
@@ -1 +1 @@
-52197
\ No newline at end of file
+30322
\ No newline at end of file
diff --git a/foundry.toml b/foundry.toml
index 27013c9c..d4140c39 100644
--- a/foundry.toml
+++ b/foundry.toml
@@ -1,5 +1,5 @@
 [profile.default]
-solc = "0.8.17"
+solc = "0.8.28"
 bytecode_hash = "none"
 optimizer = true
 via_ir = true
diff --git a/src/AllowanceTransfer.sol b/src/AllowanceTransfer.sol
index 56c4cce0..b8d9bdd8 100644
--- a/src/AllowanceTransfer.sol
+++ b/src/AllowanceTransfer.sol
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-pragma solidity 0.8.17;
+pragma solidity 0.8.28;
 
 import {ERC20} from "solmate/src/tokens/ERC20.sol";
 import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
diff --git a/src/EIP712.sol b/src/EIP712.sol
index 971a03db..4b3db17c 100644
--- a/src/EIP712.sol
+++ b/src/EIP712.sol
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-pragma solidity 0.8.17;
+pragma solidity 0.8.28;
 
 import {IEIP712} from "./interfaces/IEIP712.sol";
 
diff --git a/src/FlashAllowanceTransfer.sol b/src/FlashAllowanceTransfer.sol
new file mode 100644
index 00000000..ac64b205
--- /dev/null
+++ b/src/FlashAllowanceTransfer.sol
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: MIT
+pragma solidity 0.8.28;
+
+import {ERC20} from "solmate/src/tokens/ERC20.sol";
+import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
+import {IAllowanceTransfer} from "./interfaces/IAllowanceTransfer.sol";
+import {IFlashAllowanceTransfer} from "./interfaces/IFlashAllowanceTransfer.sol";
+
+contract FlashAllowanceTransfer is IFlashAllowanceTransfer {
+    using SafeTransferLib for ERC20;
+
+    bytes32 private constant _TEMPORARY_ALLOWANCES_SLOT = bytes32(uint256(keccak256("Allowance.allowance")) - 1);
+
+    /// @notice Maps users to tokens to spender addresses and information about the approval on the token
+    /// @dev Indexed in the order of token owner address, token address, spender address
+    /// @dev The stored word saves the allowed amount. Defined and commented, but used equivalent in inline assembly.
+    //mapping(address => mapping(address => mapping(address => uint256))) private allowance;
+
+    /// @inheritdoc IFlashAllowanceTransfer
+    /// @dev Does not emit event as approval is reset at the end of txn, and an event is emitted by the transferFrom call
+    function flashApprove(address token, address spender, uint256 amount) external {
+        _setTemporaryAllowance(msg.sender, token, spender, amount);
+    }
+
+    /// @inheritdoc IFlashAllowanceTransfer
+    function flashTransferFrom(address from, address to, uint256 amount, address token) external {
+        _flashTransfer(from, to, amount, token);
+    }
+
+    /// @inheritdoc IFlashAllowanceTransfer
+    function flashTransferFrom(IAllowanceTransfer.AllowanceTransferDetails[] calldata transferDetails) external {
+        unchecked {
+            uint256 length = transferDetails.length;
+            for (uint256 i = 0; i < length; ++i) {
+                IAllowanceTransfer.AllowanceTransferDetails memory transferDetail = transferDetails[i];
+                _flashTransfer(transferDetail.from, transferDetail.to, uint256(transferDetail.amount), transferDetail.token);
+            }
+        }
+    }
+
+    /// @notice Internal function for transferring tokens using transient allowances
+    function _flashTransfer(address from, address to, uint256 amount, address token) private {
+        uint256 allowedAmount = _getTemporaryAllowance(from, token, msg.sender);
+
+        if (allowedAmount != type(uint256).max) {
+            if (amount > allowedAmount) {
+                revert IAllowanceTransfer.InsufficientAllowance(allowedAmount);
+            } else {
+                unchecked {
+                    allowedAmount -= amount;
+                }
+            }
+        }
+
+        // Transfer the tokens from the from address to the recipient.
+        ERC20(token).safeTransferFrom(from, to, amount);
+    }
+
+    function _setTemporaryAllowance(address owner, address token, address spender, uint256 value) internal {
+        bytes32 slot = _allowanceSlot(owner, token, spender);
+        assembly ("memory-safe") {
+            tstore(slot, value)
+        }
+    }
+
+    function _getTemporaryAllowance(address owner, address token, address spender) internal view returns (uint256 allowed) {
+        bytes32 slot = _allowanceSlot(owner, token, spender);
+        assembly ("memory-safe") {
+            allowed := tload(slot)
+        }
+    }
+
+    /// @notice Returns the position key for the allowance
+    /// @dev equivalent to mapping(address => mapping(address => mapping(address => uint256)))
+    function _allowanceSlot(address owner, address spender, address token) private pure returns (bytes32) {
+        return keccak256(abi.encode(spender, keccak256(abi.encode(token, keccak256(abi.encode(owner, _TEMPORARY_ALLOWANCES_SLOT))))));
+    }
+}
diff --git a/src/Permit2.sol b/src/Permit2.sol
index 7249e40a..8f48813f 100644
--- a/src/Permit2.sol
+++ b/src/Permit2.sol
@@ -1,11 +1,12 @@
 // SPDX-License-Identifier: MIT
-pragma solidity 0.8.17;
+pragma solidity 0.8.28;
 
 import {SignatureTransfer} from "./SignatureTransfer.sol";
 import {AllowanceTransfer} from "./AllowanceTransfer.sol";
+import {FlashAllowanceTransfer} from "./FlashAllowanceTransfer.sol";
 
 /// @notice Permit2 handles signature-based transfers in SignatureTransfer and allowance-based transfers in AllowanceTransfer.
 /// @dev Users must approve Permit2 before calling any of the transfer functions.
-contract Permit2 is SignatureTransfer, AllowanceTransfer {
-// Permit2 unifies the two contracts so users have maximal flexibility with their approval.
+contract Permit2 is SignatureTransfer, AllowanceTransfer, FlashAllowanceTransfer {
+// Permit2 unifies the three contracts so users have maximal flexibility with their approval.
 }
diff --git a/src/PermitErrors.sol b/src/PermitErrors.sol
index 2c42e2d1..8e84ac91 100644
--- a/src/PermitErrors.sol
+++ b/src/PermitErrors.sol
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-pragma solidity 0.8.17;
+pragma solidity 0.8.28;
 
 /// @notice Shared errors between signature based transfers and allowance based transfers.
 
diff --git a/src/SignatureTransfer.sol b/src/SignatureTransfer.sol
index c026553a..54b7717e 100644
--- a/src/SignatureTransfer.sol
+++ b/src/SignatureTransfer.sol
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-pragma solidity 0.8.17;
+pragma solidity 0.8.28;
 
 import {ISignatureTransfer} from "./interfaces/ISignatureTransfer.sol";
 import {SignatureExpired, InvalidNonce} from "./PermitErrors.sol";
diff --git a/src/interfaces/IFlashAllowanceTransfer.sol b/src/interfaces/IFlashAllowanceTransfer.sol
new file mode 100644
index 00000000..42f9f225
--- /dev/null
+++ b/src/interfaces/IFlashAllowanceTransfer.sol
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "./IAllowanceTransfer.sol";
+
+/// @title AllowanceTransfer
+/// @notice Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts
+/// @dev Requires user's token approval on the Permit2 contract
+interface IFlashAllowanceTransfer {
+    /// @notice Approves the spender to use up to amount of the specified token
+    /// @param token The token to approve
+    /// @param spender The spender address to approve
+    /// @param amount The approved amount of the token
+    /// @dev Setting amount to type(uint160).max sets an unlimited approval
+    function flashApprove(address token, address spender, uint256 amount) external;
+
+    /// @notice Transfer approved tokens from one address to another
+    /// @param from The address to transfer from
+    /// @param to The address of the recipient
+    /// @param amount The amount of the token to transfer
+    /// @param token The token address to transfer
+    /// @dev Requires the from address to have approved at least the desired amount
+    /// of tokens to msg.sender.
+    function flashTransferFrom(address from, address to, uint256 amount, address token) external;
+
+    /// @notice Transfer approved tokens in a batch
+    /// @param transferDetails Array of owners, recipients, amounts, and tokens for the transfers
+    /// @dev Requires the from addresses to have approved at least the desired amount
+    /// of tokens to msg.sender.
+    function flashTransferFrom(IAllowanceTransfer.AllowanceTransferDetails[] calldata transferDetails) external;
+}
diff --git a/test/AllowanceTransferInvariants.t.sol b/test/AllowanceTransferInvariants.t.sol
index a980f7ce..4b9e5fbf 100644
--- a/test/AllowanceTransferInvariants.t.sol
+++ b/test/AllowanceTransferInvariants.t.sol
@@ -1,4 +1,4 @@
-pragma solidity 0.8.17;
+pragma solidity 0.8.28;
 
 import {Test} from "forge-std/Test.sol";
 import {StdInvariant} from "forge-std/StdInvariant.sol";
diff --git a/test/actors/Permitter.sol b/test/actors/Permitter.sol
index 76dbbc17..3aff7b29 100644
--- a/test/actors/Permitter.sol
+++ b/test/actors/Permitter.sol
@@ -1,4 +1,4 @@
-pragma solidity 0.8.17;
+pragma solidity 0.8.28;
 
 import {Vm} from "forge-std/Vm.sol";
 import {Permit2} from "../../src/Permit2.sol";
diff --git a/test/actors/Spender.sol b/test/actors/Spender.sol
index 22483789..919265c4 100644
--- a/test/actors/Spender.sol
+++ b/test/actors/Spender.sol
@@ -1,4 +1,4 @@
-pragma solidity 0.8.17;
+pragma solidity 0.8.28;
 
 import {Test} from "forge-std/Test.sol";
 import {Permit2} from "../../src/Permit2.sol";