Skip to content

Commit 9dcf97f

Browse files
committed
Updated validators to move entry points and data types to the top
1 parent e7d103a commit 9dcf97f

14 files changed

Lines changed: 512 additions & 516 deletions

File tree

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ group = 'com.example'
77
version = '0.1.0'
88

99
ext {
10-
julcVersion = '0.1.0-48ebb76-SNAPSHOT'
10+
julcVersion = '0.1.0-055d17f-SNAPSHOT'
1111
cardanoClientLibVersion = '0.8.0-preview1'
1212
}
1313

src/main/java/com/example/benchmark/wingriders/WingRidersPoolValidator.java

Lines changed: 86 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -55,92 +55,6 @@ record PoolDatum(byte[] requestHash, byte[] aPolicyId, byte[] aAssetName,
5555
// --- Pool redeemer ---
5656
record Evolve(List<BigInteger> requestIndices) {}
5757

58-
/**
59-
* Check compensation output datum based on beneficiary type.
60-
*/
61-
static boolean checkOutputDatum(boolean beneficiaryIsScript, TxOut compensationOutput) {
62-
OutputDatum outDatum = compensationOutput.datum();
63-
if (beneficiaryIsScript) {
64-
return switch (outDatum) {
65-
case OutputDatum.OutputDatumHash dh -> ByteStringLib.equals((byte[])(Object) dh.hash(), enforcedScriptOutputDatumHash);
66-
case OutputDatum.NoOutputDatum no -> false;
67-
case OutputDatum.OutputDatumInline inl -> false;
68-
};
69-
} else {
70-
return switch (outDatum) {
71-
case OutputDatum.NoOutputDatum no -> true;
72-
case OutputDatum.OutputDatumHash dh -> false;
73-
case OutputDatum.OutputDatumInline inl -> false;
74-
};
75-
}
76-
}
77-
78-
/**
79-
* Action-specific validation.
80-
*/
81-
static boolean checkAction(RequestAction action, byte[] beneficiaryHash, boolean beneficiaryIsScript,
82-
Value requestValue, Value compensationValue,
83-
byte[] poolAPolicyId, byte[] shareAssetName) {
84-
return switch (action) {
85-
case ExtractTreasury et -> {
86-
yield beneficiaryIsScript && ByteStringLib.equals(beneficiaryHash, treasuryHolderScriptHash);
87-
}
88-
case AddStakingRewards asr -> {
89-
boolean aIsAda = ByteStringLib.length(poolAPolicyId) == 0;
90-
BigInteger requestRewardQty = ValuesLib.assetOf(requestValue, stakingRewardsPolicyId, shareAssetName);
91-
BigInteger compensationRewardQty = ValuesLib.assetOf(compensationValue, stakingRewardsPolicyId, shareAssetName);
92-
yield aIsAda
93-
&& requestRewardQty.compareTo(BigInteger.ONE) == 0
94-
&& compensationRewardQty.compareTo(BigInteger.ONE) == 0;
95-
}
96-
case Swap s -> true;
97-
case AddLiquidity al -> true;
98-
case WithdrawLiquidity wl -> true;
99-
};
100-
}
101-
102-
/**
103-
* Validate a single request.
104-
*/
105-
static boolean validateSingleRequest(TxInInfo requestInput, TxOut compensationOutput,
106-
RequestDatum requestDatum,
107-
BigInteger txValidityEnd, byte[] requestHash,
108-
byte[] aPolicyId, byte[] aAssetName,
109-
byte[] bPolicyId, byte[] bAssetName,
110-
byte[] shareAssetName) {
111-
TxOut requestOutput = requestInput.resolved();
112-
113-
// 1. Compensation address matches beneficiary
114-
byte[] compensationCredHash = WingRidersUtils.credentialHash(compensationOutput.address());
115-
boolean addressMatch = ByteStringLib.equals(requestDatum.beneficiaryHash(), compensationCredHash);
116-
117-
// 2. Deadline not exceeded
118-
boolean deadlineOk = txValidityEnd.compareTo(requestDatum.deadline()) < 0;
119-
120-
// 3. Input script hash matches request hash
121-
byte[] inputScriptHash = WingRidersUtils.credentialHash(requestOutput.address());
122-
boolean scriptHashMatch = ByteStringLib.equals(inputScriptHash, requestHash);
123-
124-
// 4-5. Token policy/name matches
125-
boolean aPolicyMatch = ByteStringLib.equals(requestDatum.aPolicyId(), aPolicyId);
126-
boolean aNameMatch = ByteStringLib.equals(requestDatum.aAssetName(), aAssetName);
127-
boolean bPolicyMatch = ByteStringLib.equals(requestDatum.bPolicyId(), bPolicyId);
128-
boolean bNameMatch = ByteStringLib.equals(requestDatum.bAssetName(), bAssetName);
129-
130-
// 6. Correct output datum
131-
boolean datumOk = checkOutputDatum(requestDatum.beneficiaryIsScript(), compensationOutput);
132-
133-
// 7. Action-specific checks
134-
boolean actionOk = checkAction(requestDatum.action(), requestDatum.beneficiaryHash(),
135-
requestDatum.beneficiaryIsScript(),
136-
requestOutput.value(), compensationOutput.value(),
137-
aPolicyId, shareAssetName);
138-
139-
return addressMatch && deadlineOk && scriptHashMatch
140-
&& aPolicyMatch && aNameMatch && bPolicyMatch && bNameMatch
141-
&& datumOk && actionOk;
142-
}
143-
14458
@Entrypoint
14559
public static boolean validate(PoolDatum datum, Evolve redeemer, ScriptContext ctx) {
14660
TxInfo txInfo = ctx.txInfo();
@@ -201,4 +115,90 @@ public static boolean validate(PoolDatum datum, Evolve redeemer, ScriptContext c
201115

202116
return allValid;
203117
}
118+
119+
/**
120+
* Validate a single request.
121+
*/
122+
static boolean validateSingleRequest(TxInInfo requestInput, TxOut compensationOutput,
123+
RequestDatum requestDatum,
124+
BigInteger txValidityEnd, byte[] requestHash,
125+
byte[] aPolicyId, byte[] aAssetName,
126+
byte[] bPolicyId, byte[] bAssetName,
127+
byte[] shareAssetName) {
128+
TxOut requestOutput = requestInput.resolved();
129+
130+
// 1. Compensation address matches beneficiary
131+
byte[] compensationCredHash = WingRidersUtils.credentialHash(compensationOutput.address());
132+
boolean addressMatch = ByteStringLib.equals(requestDatum.beneficiaryHash(), compensationCredHash);
133+
134+
// 2. Deadline not exceeded
135+
boolean deadlineOk = txValidityEnd.compareTo(requestDatum.deadline()) < 0;
136+
137+
// 3. Input script hash matches request hash
138+
byte[] inputScriptHash = WingRidersUtils.credentialHash(requestOutput.address());
139+
boolean scriptHashMatch = ByteStringLib.equals(inputScriptHash, requestHash);
140+
141+
// 4-5. Token policy/name matches
142+
boolean aPolicyMatch = ByteStringLib.equals(requestDatum.aPolicyId(), aPolicyId);
143+
boolean aNameMatch = ByteStringLib.equals(requestDatum.aAssetName(), aAssetName);
144+
boolean bPolicyMatch = ByteStringLib.equals(requestDatum.bPolicyId(), bPolicyId);
145+
boolean bNameMatch = ByteStringLib.equals(requestDatum.bAssetName(), bAssetName);
146+
147+
// 6. Correct output datum
148+
boolean datumOk = checkOutputDatum(requestDatum.beneficiaryIsScript(), compensationOutput);
149+
150+
// 7. Action-specific checks
151+
boolean actionOk = checkAction(requestDatum.action(), requestDatum.beneficiaryHash(),
152+
requestDatum.beneficiaryIsScript(),
153+
requestOutput.value(), compensationOutput.value(),
154+
aPolicyId, shareAssetName);
155+
156+
return addressMatch && deadlineOk && scriptHashMatch
157+
&& aPolicyMatch && aNameMatch && bPolicyMatch && bNameMatch
158+
&& datumOk && actionOk;
159+
}
160+
161+
/**
162+
* Action-specific validation.
163+
*/
164+
static boolean checkAction(RequestAction action, byte[] beneficiaryHash, boolean beneficiaryIsScript,
165+
Value requestValue, Value compensationValue,
166+
byte[] poolAPolicyId, byte[] shareAssetName) {
167+
return switch (action) {
168+
case ExtractTreasury et -> {
169+
yield beneficiaryIsScript && ByteStringLib.equals(beneficiaryHash, treasuryHolderScriptHash);
170+
}
171+
case AddStakingRewards asr -> {
172+
boolean aIsAda = ByteStringLib.length(poolAPolicyId) == 0;
173+
BigInteger requestRewardQty = ValuesLib.assetOf(requestValue, stakingRewardsPolicyId, shareAssetName);
174+
BigInteger compensationRewardQty = ValuesLib.assetOf(compensationValue, stakingRewardsPolicyId, shareAssetName);
175+
yield aIsAda
176+
&& requestRewardQty.compareTo(BigInteger.ONE) == 0
177+
&& compensationRewardQty.compareTo(BigInteger.ONE) == 0;
178+
}
179+
case Swap s -> true;
180+
case AddLiquidity al -> true;
181+
case WithdrawLiquidity wl -> true;
182+
};
183+
}
184+
185+
/**
186+
* Check compensation output datum based on beneficiary type.
187+
*/
188+
static boolean checkOutputDatum(boolean beneficiaryIsScript, TxOut compensationOutput) {
189+
OutputDatum outDatum = compensationOutput.datum();
190+
if (beneficiaryIsScript) {
191+
return switch (outDatum) {
192+
case OutputDatum.OutputDatumHash dh -> ByteStringLib.equals((byte[])(Object) dh.hash(), enforcedScriptOutputDatumHash);
193+
case OutputDatum.NoOutputDatum no -> false;
194+
case OutputDatum.OutputDatumInline inl -> false;
195+
};
196+
} else {
197+
return switch (outDatum) {
198+
case OutputDatum.NoOutputDatum no -> true;
199+
case OutputDatum.OutputDatumHash dh -> false;
200+
case OutputDatum.OutputDatumInline inl -> false;
201+
};
202+
}
203+
}
204204
}

src/main/java/com/example/lending/onchain/CollateralLoan.java

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,24 +50,16 @@ public record TakeLoan() implements LoanAction {}
5050
public record RepayLoan() implements LoanAction {}
5151
public record Liquidate() implements LoanAction {}
5252

53-
static BigInteger calculateInterest(BigInteger principal) {
54-
return principal.multiply(interestRateBps).divide(BigInteger.valueOf(10000));
55-
}
56-
57-
static BigInteger totalRepayment(BigInteger principal) {
58-
return principal.add(calculateInterest(principal));
59-
}
60-
61-
static boolean hasEnoughCollateral(BigInteger collateral, BigInteger principal) {
62-
// collateral * 10000 >= principal * liquidationThresholdBps
63-
return collateral.multiply(BigInteger.valueOf(10000)).compareTo(
64-
principal.multiply(liquidationThresholdBps)) >= 0;
65-
}
66-
67-
static Address toAddress(byte[] pkh) {
68-
return new Address(
69-
new Credential.PubKeyCredential(PubKeyHash.of(pkh)),
70-
Optional.empty());
53+
@Entrypoint
54+
public static boolean validate(LoanDatum datum, LoanAction redeemer, ScriptContext ctx) {
55+
TxInfo txInfo = ctx.txInfo();
56+
ContextsLib.trace("CollateralLoan validate");
57+
return switch (redeemer) {
58+
case OfferLoan o -> validateOfferLoan(datum, txInfo);
59+
case TakeLoan t -> validateTakeLoan(datum, txInfo);
60+
case RepayLoan r -> validateRepayLoan(datum, txInfo);
61+
case Liquidate l -> validateLiquidate(datum, txInfo);
62+
};
7163
}
7264

7365
static boolean validateOfferLoan(LoanDatum datum, TxInfo txInfo) {
@@ -110,15 +102,23 @@ static boolean validateLiquidate(LoanDatum datum, TxInfo txInfo) {
110102
return lenderSigned && afterDeadline;
111103
}
112104

113-
@Entrypoint
114-
public static boolean validate(LoanDatum datum, LoanAction redeemer, ScriptContext ctx) {
115-
TxInfo txInfo = ctx.txInfo();
116-
ContextsLib.trace("CollateralLoan validate");
117-
return switch (redeemer) {
118-
case OfferLoan o -> validateOfferLoan(datum, txInfo);
119-
case TakeLoan t -> validateTakeLoan(datum, txInfo);
120-
case RepayLoan r -> validateRepayLoan(datum, txInfo);
121-
case Liquidate l -> validateLiquidate(datum, txInfo);
122-
};
105+
static Address toAddress(byte[] pkh) {
106+
return new Address(
107+
new Credential.PubKeyCredential(PubKeyHash.of(pkh)),
108+
Optional.empty());
109+
}
110+
111+
static boolean hasEnoughCollateral(BigInteger collateral, BigInteger principal) {
112+
// collateral * 10000 >= principal * liquidationThresholdBps
113+
return collateral.multiply(BigInteger.valueOf(10000)).compareTo(
114+
principal.multiply(liquidationThresholdBps)) >= 0;
115+
}
116+
117+
static BigInteger totalRepayment(BigInteger principal) {
118+
return principal.add(calculateInterest(principal));
119+
}
120+
121+
static BigInteger calculateInterest(BigInteger principal) {
122+
return principal.multiply(interestRateBps).divide(BigInteger.valueOf(10000));
123123
}
124124
}

0 commit comments

Comments
 (0)