11# pragma version 0.4.3
22# pragma nonreentrancy on
3+ """
4+ @title Purse Accessory - ERC3156 Flashloan Callback
5+ @author Purse contributors
6+ @dev
7+ This contract implements the `ERC3156FlashBorrower` interface and logic,
8+ so that the Purse can handle the flash loan context and continue operation
9+ by performing the encoded call provided with the callback data.
10+
11+ It should not be possible for anyone besides the Purse itself to call this,
12+ as that would allow aribtrary approvals to malicious addresses, as well as
13+ enable arbitrary delegate calls more generally, if it was improperly handled.
14+ """
315from ethereum.ercs import IERC20
416
517interface IERC3156FlashBorrower :
@@ -21,17 +33,28 @@ def onFlashLoan(
2133 token: IERC20,
2234 amount: uint256 ,
2335 fee: uint256 ,
24- data: Bytes[65535 ],
36+ data: Bytes[1 + 65535 + 32 * 2 ],
2537) -> bytes32 :
26- # NOTE: Only trusted context allowed
27- assert initiator == self , "Flashloan:!authorized "
28-
29- # NOTE: Ensure that appropriate amount of allowance is given to caller
30- if staticcall token.allowance (tx .origin , msg .sender ) < amount + fee:
31- extcall token.approve (msg .sender , amount + fee)
32-
33- # NOTE: Forward whatever we specified to follow-up with back to ourselves
34- raw_call (tx .origin , data)
38+ """
39+ @notice Handle the ERC3156 Flashloan Callback
40+ @param initiator The initiator of the flash loan (ignored, should be `self`)
41+ @param token The token used for the flash loan
42+ @param amount The amount of `token` that is loaned
43+ @param fee The amount of `token` that must be repaid for borrowing `amount`
44+ @param data The encoded internal call to make, encoded as `to|value|data`
45+ @return The magic value `keccak256("ERC3156FlashBorrower.onFlashLoan")`
46+ """
47+ # NOTE: Only purse is allowed to do this
48+ assert tx .origin == self , "Flashloan:!authorized "
49+
50+ # NOTE: Ensure that appropriate amount of allowance is made available to caller
51+ assert extcall token.approve (msg .sender , amount + fee, default_return_value= True )
52+
53+ # Perform encoded call as Purse
54+ to: address = empty (address )
55+ amt: uint256 = 0
56+ to, amt = abi_decode (slice (data, 0 , 32 * 2 ), (address , uint256 ))
57+ raw_call (to, slice (data, 32 * 2 , len (data)), value= amt)
3558
3659 # NOTE: Magic value per ERC-3156
3760 return keccak256 ("ERC3156FlashBorrower.onFlashLoan " )
0 commit comments