# non-custodial flash loans with transient storage Powerful pattern enabled by transient storage. The user calls `NonCustodialFlashLoans#startLoan`, and control is handed back to them using the `IStartCallback#start` callback. The user can then borrow as much of any token they want, from any user that has sent approval, within this callback by calling `NonCustodialFlashLoans#borrow`. The contract uses transient storage to track what has been borrowed and check the tokens are returned at the end. ***The SLOAD/SSTORE’s make this pattern gas-infeasible without transient storage.*** Credit: @sendmoodz for this idea > Disclaimer: Unaudited code ```solidity interface IStartCallback { /// @notice Called on the `msg.sender` to hand over control to them. /// Expectation is that msg.sender#start will borrow tokens using NonCustodialFlashLoans#borrow, /// then return them to the original user before control is handed back to #start. function start() external; } contract NonCustodialFlashLoans { struct Borrow { uint256 lenderStartingBalance; address lender; IERC20 token; } // The full list of borrows that have occured in the current transaction. Borrow[] public transient borrows; // The user borrowing. Borrower is able to call #borrow to release tokens. address public transient borrower; /// @notice Entry Point. Start borrowing from the users that have approved this contract. function startLoan() external { require(borrower == address(0)); // prevent reentrance // TSTORE it! borrower = msg.sender; /// Hand control to the caller so they can start borrowing tokens IStartCallback(msg.sender).start(); // At this point `msg.sender` should have returned any tokens that // were borrowed to each lender. Check this and revert if not! for (uint256 i = 0; i < borrows.length; i++) { Borrow transient borrow = borrows[i]; // TLOAD! require( borrow.token.balanceOf(borrow.lender) >= borrow.lenderStartingBalance, 'You must pay back the person you borrowed from!' ); } borrows.length = 0; // this doesn't actually work in recent solidity versions for storage arrays, but we only need to set the length of the array, you can also use TSTORE directly borrower = address(0); // clearing this allows it to be called again in the same transaction } // Only callable by `borrower`. Used to borrow tokens. function borrow( address from, IERC20 token, uint256 amount, address to ) external { require(msg.sender == borrower, 'Must be called from within the IStartCallback#start'); // TSTORE what has been borrowed borrows.push(Borrow({lenderStartingBalance: token.balanceOf(from), lender: from, token: token})); token.transferFrom(from, to, amount); } } ```