-
-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathflashloan.py
More file actions
68 lines (58 loc) · 2.11 KB
/
Copy pathflashloan.py
File metadata and controls
68 lines (58 loc) · 2.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
from opshin.prelude import *
from opshin.std.fractions import *
@dataclass
class FlashloanParams(PlutusData):
CONSTR_ID = 0
owner: PubKeyHash
loan_token: Token
loan_fee: Fraction
@dataclass
class FlashloanState(PlutusData):
CONSTR_ID = 0
params: FlashloanParams
spent_for: TxOutRef
@dataclass
class FlashLend(PlutusData):
CONSTR_ID = 0
input_index: int
output_index: int
@dataclass
class FlashWithdraw(PlutusData):
CONSTR_ID = 1
def validator(
state: FlashloanState,
redeemer: Union[FlashLend, FlashWithdraw],
context: ScriptContext,
) -> None:
tx_info = context.tx_info
purpose: Spending = context.purpose
if isinstance(redeemer, FlashWithdraw):
assert state.params.owner in tx_info.signatories, "Only the owner can withdraw"
elif isinstance(redeemer, FlashLend):
own_input_info = tx_info.inputs[redeemer.input_index]
assert (
own_input_info.out_ref == purpose.tx_out_ref
), "Input index must match the spent utxo"
own_input = own_input_info.resolved
own_output = tx_info.outputs[redeemer.output_index]
assert (
own_output.address == own_input.address
), "Output must be sent back to contract"
assert own_output.datum == SomeOutputDatum(
FlashloanState(state.params, purpose.tx_out_ref)
)
loan_token = state.params.loan_token
for pid, name_amount_dict in own_input.value.items():
for name, amount in name_amount_dict.items():
if Token(pid, name) == loan_token:
assert ge_fraction(
mul_fraction(Fraction(amount, 1), state.params.loan_fee),
Fraction(own_output.value[pid][name], 1),
), "Output must satisfy loan fee"
else:
assert (
own_output.value[pid][name] == amount
), "Output must have same value as input"
assert len(own_output.to_cbor()) <= 1000, "Output must be less than 1000 bytes"
else:
assert False, "Invalid redeemer"