Skip to content

Commit

Permalink
v0 of the starport validator
Browse files Browse the repository at this point in the history
  • Loading branch information
androolloyd committed Dec 15, 2023
1 parent 2ed722a commit df93a7c
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 10 deletions.
30 changes: 30 additions & 0 deletions scripts/verify.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# takes in a deployment file and the chain id verifies on etherscan
# needs to have ETHERSCAN_API_KEY set in the environment
set -e
INPUT_FILE=$1
ARG_FILE="$(dirname $INPUT_FILE)/arguments.json"
CHAIN_ID=$(jq -r '.chain' < $INPUT_FILE)
COMPILER_VERSION="0.8.17"
for row in $(jq -c '.transactions[]' < ${INPUT_FILE}); do
_jq() {
echo ${row} | jq -r ${1}
}

if [[ $(_jq '.transactionType') == "CREATE" ]]; then

args=$(_jq '.arguments')
CONSTRUCTOR_ARGS_PATH=""
if [[ ${args} != "null" ]]; then
echo ${args} > "${ARG_FILE}"
CONSTRUCTOR_ARGS_PATH=--constructor-args-path=${ARG_FILE}
fi
if ! forge verify-contract "$(_jq '.contractAddress')" "$(_jq '.contractName')" -e ${ETHERSCAN_API_KEY} --chain ${CHAIN_ID} --compiler-version ${COMPILER_VERSION} ${CONSTRUCTOR_ARGS_PATH}
then
echo "failed to verify $(_jq '.contractName')"
continue
fi

fi
done
rm -f ${ARG_FILE}
2 changes: 1 addition & 1 deletion src/lib/StarportLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ library StarportLib {
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

function calculateSimpleInterest(uint256 delta_t, uint256 amount, uint256 rate, uint256 decimals)
public
internal
pure
returns (uint256)
{
Expand Down
120 changes: 120 additions & 0 deletions src/lib/StarportValidator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
pragma solidity ^0.8.0;

import {Validation} from "./Validation.sol";
import {Starport} from "../Starport.sol";
import {Custodian} from "../Custodian.sol";
import {Pricing} from "../pricing/Pricing.sol";
import {Status} from "../status/Status.sol";
import {Settlement} from "../settlement/Settlement.sol";
import {SignatureCheckerLib} from "solady/src/utils/SignatureCheckerLib.sol";
import {CaveatEnforcer} from "../enforcers/CaveatEnforcer.sol";
import {AdditionalTransfer} from "./StarportLib.sol";

contract StarportValidator {
struct ValidationError {
ErrorSet[] errors;
}

struct ErrorSet {
string msg;
CODES codes;
}

//is the sig valid
//are the params valid
//are these module contracts we approve
//is there time remaining
//has the salt been filled
//is the nonce correct
enum CODES {
INVALID_MODULE,
EMPTY_CAVEAT,
VALIDATION,
CAVEAT_EXPIRED,
INVALID_CAVEAT,
INVALID_CAVEAT_LENGTH,
INVALID_SALT,
INVALID_HASH,
INVALID_SIGNATURE
}

ValidationError private validation;

function validateOriginate(
address[3] memory validModules, //pricing,status,settlement
Starport starport,
Custodian custodian,
address fulfiller,
AdditionalTransfer[] calldata additionalTransfers,
CaveatEnforcer.SignedCaveats calldata borrowerCaveat,
CaveatEnforcer.SignedCaveats calldata lenderCaveat,
Starport.Loan memory loan
) public returns (bytes memory output) {
if (fulfiller != loan.borrower) {
if (keccak256(abi.encode(borrowerCaveat)) == _emptyCaveatHash()) {
validation.errors.push(ErrorSet({msg: "Borrower", codes: CODES.EMPTY_CAVEAT}));
} else if (borrowerCaveat.deadline > block.timestamp) {
validation.errors.push(ErrorSet({msg: "Borrower", codes: CODES.CAVEAT_EXPIRED}));
}

bytes32 caveatHash = starport.hashCaveatWithSaltAndNonce(
fulfiller,
borrowerCaveat.singleUse,
borrowerCaveat.salt,
borrowerCaveat.deadline,
borrowerCaveat.caveats
);
if (starport.invalidSalts(fulfiller, caveatHash)) {
validation.errors.push(ErrorSet({msg: "Borrower", codes: CODES.INVALID_SALT}));
}
if (!SignatureCheckerLib.isValidSignatureNowCalldata(fulfiller, caveatHash, borrowerCaveat.signature)) {
validation.errors.push(ErrorSet({msg: "Borrower", codes: CODES.INVALID_SIGNATURE}));
}
}
if (fulfiller != loan.issuer) {
if (keccak256(abi.encode(lenderCaveat)) == _emptyCaveatHash()) {
validation.errors.push(ErrorSet({msg: "Lender", codes: CODES.EMPTY_CAVEAT}));
} else if (lenderCaveat.deadline > block.timestamp) {
validation.errors.push(ErrorSet({msg: "Lender", codes: CODES.CAVEAT_EXPIRED}));
}

bytes32 caveatHash = starport.hashCaveatWithSaltAndNonce(
fulfiller, lenderCaveat.singleUse, lenderCaveat.salt, lenderCaveat.deadline, lenderCaveat.caveats
);
if (starport.invalidSalts(fulfiller, caveatHash)) {
validation.errors.push(ErrorSet({msg: "Lender", codes: CODES.INVALID_SALT}));
}
if (!SignatureCheckerLib.isValidSignatureNowCalldata(fulfiller, caveatHash, lenderCaveat.signature)) {
validation.errors.push(ErrorSet({msg: "Lender", codes: CODES.INVALID_SIGNATURE}));
}
}
if (validModules[0] != loan.terms.pricing) {
validation.errors.push(ErrorSet({msg: "Pricing", codes: CODES.INVALID_MODULE}));
}
if (validModules[1] != loan.terms.status) {
validation.errors.push(ErrorSet({msg: "Status", codes: CODES.INVALID_MODULE}));
}
if (validModules[2] != loan.terms.settlement) {
validation.errors.push(ErrorSet({msg: "Settlement", codes: CODES.INVALID_MODULE}));
}
if (loan.custodian != address(custodian)) {
validation.errors.push(ErrorSet({msg: "Custodian", codes: CODES.INVALID_MODULE}));
}
if (Pricing(loan.terms.pricing).validate(loan) != Validation.validate.selector) {
validation.errors.push(ErrorSet({msg: "Pricing", codes: CODES.VALIDATION}));
}
if (Status(loan.terms.status).validate(loan) != Validation.validate.selector) {
validation.errors.push(ErrorSet({msg: "Status", codes: CODES.VALIDATION}));
}
if (Settlement(loan.terms.settlement).validate(loan) != Validation.validate.selector) {
validation.errors.push(ErrorSet({msg: "Settlement", codes: CODES.VALIDATION}));
}

return abi.encode(validation);
}

function _emptyCaveatHash() internal returns (bytes32) {
CaveatEnforcer.SignedCaveats memory emptyCaveat;
return keccak256(abi.encode(emptyCaveat));
}
}
21 changes: 21 additions & 0 deletions src/scripts/Deploy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
pragma solidity ^0.8.0;

import "forge-std/Script.sol";

import {Starport, Stargate} from "starport-core/Starport.sol";
import {SimpleInterestPricing} from "starport-core/pricing/SimpleInterestPricing.sol";
import {FixedTermStatus} from "starport-core/status/FixedTermStatus.sol";
import {FixedTermDutchAuctionSettlement} from "starport-core/settlement/FixedTermDutchAuctionSettlement.sol";

contract Deploy is Script {
address public constant seaport = address(0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC);

function run() public {
vm.startBroadcast();
Starport SP = new Starport(seaport, Stargate(address(0)));
new FixedTermDutchAuctionSettlement(SP);
new FixedTermStatus();
new SimpleInterestPricing(SP);
vm.stopBroadcast();
}
}
4 changes: 1 addition & 3 deletions test/StarportTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -558,9 +558,7 @@ contract StarportTest is BaseOrderTest, Stargate {
pure
returns (ConsiderationItem[] memory)
{
ConsiderationItem[] memory considerationItems = new ConsiderationItem[](
_receivedItems.length
);
ConsiderationItem[] memory considerationItems = new ConsiderationItem[](_receivedItems.length);
for (uint256 i = 0; i < _receivedItems.length; ++i) {
considerationItems[i] = ConsiderationItem(
_receivedItems[i].itemType,
Expand Down
8 changes: 2 additions & 6 deletions test/integration-testing/TestNewLoan.sol
Original file line number Diff line number Diff line change
Expand Up @@ -386,9 +386,7 @@ contract TestNewLoan is StarportTest {
(ReceivedItem[] memory settlementConsideration, address authorized) =
Settlement(activeLoan.terms.settlement).getSettlementConsideration(activeLoan);
settlementConsideration = StarportLib.removeZeroAmountItems(settlementConsideration);
ConsiderationItem[] memory consider = new ConsiderationItem[](
settlementConsideration.length
);
ConsiderationItem[] memory consider = new ConsiderationItem[](settlementConsideration.length);
uint256 i = 0;
for (; i < settlementConsideration.length;) {
consider[i].token = settlementConsideration[i].token;
Expand All @@ -401,9 +399,7 @@ contract TestNewLoan is StarportTest {
++i;
}
}
OfferItem[] memory repayOffering = new OfferItem[](
activeLoan.collateral.length
);
OfferItem[] memory repayOffering = new OfferItem[](activeLoan.collateral.length);
i = 0;
for (; i < activeLoan.collateral.length;) {
repayOffering[i] = OfferItem({
Expand Down

0 comments on commit df93a7c

Please sign in to comment.