Skip to content

Commit 9d0ce9e

Browse files
committed
refactor(Flashlend): add ability to set fee basis; reject 0 fee lends
1 parent a4add36 commit 9d0ce9e

2 files changed

Lines changed: 39 additions & 5 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"feeBasis": {
3+
"type": "HashMap[address, uint256]",
4+
"n_slots": 0,
5+
"slot": 154682873977518743260419555346329208424049161262037279244905357072823178018
6+
}
7+
}

contracts/accessories/Flashlend.vy

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,29 @@ interface IERC3156:
2323

2424
implements: 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
3139
def maxFlashLoan(token: IERC20) -> uint256:
40+
if self.feeBasis[token] == 0:
41+
return 0
42+
3243
return staticcall token.balanceOf(self)
3344

3445

3546
@view
3647
def _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
4869
def 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

Comments
 (0)