@@ -23,19 +23,29 @@ interface IERC3156:
2323
2424implements: IERC3156
2525
26+ # @custom:storage-location erc7201:purse.accessories.Flashlend
27+ # keccak256(abi.encode(uint256(keccak256("purse.accessories.Flashlend")) - 1)) & ~bytes32(uint256(0xff))
28+ feeBasis: HashMap[IERC20, uint256 ] # 0x578c22acf65ce07623403df1f4aaaea33129ac33b22142a968e7c121335322
29+
30+
31+ # NOTE: Can watch for generic events of this type to find Purses that have "opted-in" to flashloans
32+ event FlashFeeUpdated:
33+ token: indexed (IERC20)
34+ milli_bps: uint256
2635
27- # TODO: Configure which tokens are allowed to be transferred?
2836
2937@view
3038@external
3139def maxFlashLoan (token: IERC20) -> uint256 :
40+ if self .feeBasis[token] == 0 :
41+ return 0
42+
3243 return staticcall token.balanceOf (self )
3344
3445
3546@view
3647def _fee (token: IERC20, amount: uint256 ) -> uint256 :
37- # TODO: Make this configurable?
38- return amount // 100 # 1% fee
48+ return self .feeBasis[token] * amount // 1_000_000
3949
4050
4151@view
@@ -45,6 +55,17 @@ def flashFee(token: IERC20, amount: uint256) -> uint256:
4555
4656
4757@external
58+ def setFlashFee (token: IERC20, feeBasis: uint256 ):
59+ assert feeBasis <= 1_000_000 , "Flashlend:incorrect-fee-basis "
60+ # NOTE: Can only work in a EIP-7702 context from Purse
61+ assert tx .origin == self , "Flashlend:!authorized "
62+
63+ self .feeBasis[token] = feeBasis
64+ log FlashFeeUpdated (token= token, milli_bps= feeBasis)
65+
66+
67+ @external
68+ # NOTE: Non-reentrant
4869def flashLoan (
4970 receiver: IERC3156FlashBorrower,
5071 token: IERC20,
@@ -56,14 +77,20 @@ def flashLoan(
5677
5778 # Tell receiver about the flashloan
5879 fee: uint256 = self ._fee (token, amount)
80+ assert fee > 0 , "Flashlend:!token-allowed "
5981 assert (
6082 # NOTE: `msg.sender` is original caller of delegatecall
6183 extcall receiver.onFlashLoan (msg .sender , token, amount, fee, data)
6284 # NOTE: Magic value per ERC-3156
6385 == keccak256 ("ERC3156FlashBorrower.onFlashLoan " )
64- )
86+ ), " Flashlend:!receiver-returndata-invalid "
6587
6688 # Get our tokens back
67- assert extcall token.transferFrom (receiver.address , self , amount + fee, default_return_value= True )
89+ assert extcall token.transferFrom (
90+ receiver.address ,
91+ self ,
92+ amount + fee,
93+ default_return_value= True ,
94+ )
6895
6996 return True
0 commit comments