Skip to content

Commit

Permalink
Feat/caveat updates (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xgregthedev authored Oct 8, 2023
1 parent b1711c8 commit 75999cc
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 36 deletions.
54 changes: 28 additions & 26 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
EnforcerTest:testCollateralEnforcer() (gas: 973177)
EnforcerTest:testFailCollateralEnforcerDifferentCollateral() (gas: 855101)
EnforcerTest:testFailRateEnforcerMaxCarryRate() (gas: 810244)
EnforcerTest:testFailRateEnforcerMaxRate() (gas: 810194)
EnforcerTest:testFailRateEnforcerMaxRateAndMaxCarryRate() (gas: 810059)
EnforcerTest:testRateEnforcerBasic() (gas: 930425)
EnforcerTest:testTermEnforcerBasic() (gas: 1002689)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecall() (gas: 988282)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 906210)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 952988)
EnforcerTest:testCollateralEnforcer() (gas: 964781)
EnforcerTest:testFailCollateralEnforcerDifferentCollateral() (gas: 846753)
EnforcerTest:testFailRateEnforcerMaxCarryRate() (gas: 801907)
EnforcerTest:testFailRateEnforcerMaxRate() (gas: 801857)
EnforcerTest:testFailRateEnforcerMaxRateAndMaxCarryRate() (gas: 801722)
EnforcerTest:testRateEnforcerBasic() (gas: 922038)
EnforcerTest:testTermEnforcerBasic() (gas: 994300)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecall() (gas: 983680)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 901571)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 948381)
TestCustodian:testCustodySelector() (gas: 7152)
TestCustodian:testGenerateOrderRepay() (gas: 174157)
TestCustodian:testGenerateOrderRepay() (gas: 174179)
TestCustodian:testGenerateOrderRepayNotBorrower() (gas: 102146)
TestCustodian:testGenerateOrderSettlement() (gas: 125008)
TestCustodian:testGenerateOrderSettlementUnauthorized() (gas: 100145)
TestCustodian:testGetBorrower() (gas: 75840)
TestCustodian:testOnlySeaport() (gas: 17931)
TestCustodian:testPreviewOrderNoActiveLoan() (gas: 229)
TestCustodian:testPreviewOrderRepay() (gas: 224706)
TestCustodian:testPreviewOrderRepay() (gas: 224750)
TestCustodian:testPreviewOrderSettlement() (gas: 152470)
TestCustodian:testRatifyOrder() (gas: 188716)
TestCustodian:testRatifyOrder() (gas: 188760)
TestCustodian:testSafeTransferReceive() (gas: 159061)
TestCustodian:testSeaportMetadata() (gas: 8519)
TestCustodian:testSupportsInterface() (gas: 5791)
TestExoticLoans:testSwap() (gas: 1167541)
TestExoticLoans:testSwap() (gas: 1163700)
TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 252)
TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 521951)
TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 753642)
TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 519386)
TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 740159)
TestLoanManager:testGenerateOrder() (gas: 1009691)
TestLoanManager:testGenerateOrderInvalidSender() (gas: 13075)
TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 517630)
TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 749358)
TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 515545)
TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 735700)
TestLoanManager:testGenerateOrder() (gas: 1008482)
TestLoanManager:testGenerateOrderInvalidSender() (gas: 12986)
TestLoanManager:testSupportsInterface() (gas: 7003)
TestNewLoan:testBuyNowPayLater() (gas: 1154993)
TestNewLoan:testNewLoanERC721CollateralDefaultTerms2():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 1001549)
TestNewLoan:testNewLoanERC721CollateralDefaultTermsRefinance() (gas: 658024)
TestNewLoan:testSettleLoan() (gas: 1282926)
TestRepayLoan:testRepayLoan() (gas: 736801)
TestNewLoan:testBuyNowPayLater() (gas: 1146513)
TestNewLoan:testNewLoanERC721CollateralDefaultTerms2():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 993154)
TestNewLoan:testNewLoanERC721CollateralDefaultTermsRefinance() (gas: 653724)
TestNewLoan:testSettleLoan() (gas: 1274568)
TestRepayLoan:testRepayLoan() (gas: 732514)
TestStarLiteUtils:testEncodeReceivedWithRecipient() (gas: 17955)
TestStarLiteUtils:testSpentToReceived() (gas: 17796)
TestStarLiteUtils:testSpentToReceived() (gas: 17708)
TestStarLiteUtils:testValidateSaltOpt(address,bytes32) (runs: 256, μ: 26479, ~: 26479)
TestStarLiteUtils:testValidateSaltRef(address,bytes32) (runs: 256, μ: 26849, ~: 26849)
18 changes: 10 additions & 8 deletions src/LoanManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable

using {StarPortLib.toReceivedItems} for SpentItem[];
using {StarPortLib.getId} for LoanManager.Loan;
using {StarPortLib.validateSalt} for mapping(address => mapping(bytes32 => bool));

ConsiderationInterface public immutable seaport;
// ConsiderationInterface public constant seaport =
Expand All @@ -63,7 +64,7 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable
keccak256("IntentOrigination(bytes32 hash,bytes32 salt,uint256 nonce)");
bytes32 constant VERSION = keccak256("0");

mapping(bytes32 => bool) public usedHashes;
mapping(address => mapping(bytes32 => bool)) public usedSalts;
mapping(address => uint256) public borrowerNonce; //needs to be invalidated

address public feeTo;
Expand Down Expand Up @@ -325,11 +326,11 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable
exoticFee[exotic] = fee;
}

function getExoticFee(SpentItem memory exotic) public returns (Fee memory fee) {
function getExoticFee(SpentItem memory exotic) public view returns (Fee memory fee) {
return exoticFee[exotic.token];
}

function _feeRake(SpentItem[] memory debt) internal returns (ReceivedItem[] memory feeConsideration) {
function _feeRake(SpentItem[] memory debt) internal view returns (ReceivedItem[] memory feeConsideration) {
uint256 i = 0;
feeConsideration = new ReceivedItem[](debt.length);
for (; i < debt.length;) {
Expand Down Expand Up @@ -421,13 +422,14 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable
if (enforceCaveats) {
bytes32 caveatHash = keccak256(
encodeWithSaltAndBorrowerCounter(
obligation.borrower, obligation.salt, keccak256(abi.encode(obligation))
obligation.borrower, obligation.salt, keccak256(abi.encode(obligation.caveats))
)
);
//prevent replay on the hash
usedHashes[caveatHash] = true;
uint256 i = 0;
for (; i < obligation.caveats.length;) {

//prevent replay on the salt
usedSalts.validateSalt(obligation.borrower, obligation.salt);

for (uint256 i = 0; i < obligation.caveats.length;) {
if (!CaveatEnforcer(obligation.caveats[i].enforcer).enforceCaveat(obligation.caveats[i].terms, loan)) {
revert InvalidOrigination();
}
Expand Down
44 changes: 44 additions & 0 deletions src/lib/StarPortLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/Considera
import {LoanManager} from "starport-core/LoanManager.sol";

library StarPortLib {
error InvalidSalt();

uint256 internal constant _INVALID_SALT = 0x81e69d9b00000000000000000000000000000000000000000000000000000000;

function getId(LoanManager.Loan memory loan) internal pure returns (uint256 loanId) {
loanId = uint256(keccak256(abi.encode(loan)));
}
Expand Down Expand Up @@ -88,4 +92,44 @@ library StarPortLib {
}
}
}

function validateSaltRef(
mapping(address => mapping(bytes32 => bool)) storage usedSalts,
address borrower,
bytes32 salt
) internal {
if (usedSalts[borrower][salt]) {
revert InvalidSalt();
}
usedSalts[borrower][salt] = true;
}

function validateSalt(
mapping(address => mapping(bytes32 => bool)) storage usedSalts,
address borrower,
bytes32 salt
) internal {
assembly {
mstore(0x0, borrower)
mstore(0x20, usedSalts.slot)

//usedSalts[borrower]
let loc := keccak256(0x0, 0x40)

mstore(0x0, salt)
mstore(0x20, loc)

//usedSalts[borrower][salt]
loc := keccak256(0x0, 0x40)

//if (usedSalts[borrower][salt] == true)
if iszero(iszero(sload(loc))) {
//revert InvalidSalt()
mstore(0x0, _INVALID_SALT)
revert(0x0, 0x04)
}

sstore(loc, 1)
}
}
}
4 changes: 2 additions & 2 deletions test/StarPortTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ contract StarPortTest is BaseOrderTest {
//use murky to create a tree that is good

bytes32 caveatHash =
keccak256(LM.encodeWithSaltAndBorrowerCounter(nlr.borrower, nlr.salt, keccak256(abi.encode(nlr))));
keccak256(LM.encodeWithSaltAndBorrowerCounter(nlr.borrower, nlr.salt, keccak256(abi.encode(nlr.caveats))));
OfferItem[] memory offer = new OfferItem[](nlr.debt.length + 1);

for (uint256 i; i < debt.length;) {
Expand Down Expand Up @@ -517,7 +517,7 @@ contract StarPortTest is BaseOrderTest {
returns (LoanManager.Loan memory loan)
{
bytes32 caveatHash =
keccak256(LM.encodeWithSaltAndBorrowerCounter(nlr.borrower, nlr.salt, keccak256(abi.encode(nlr))));
keccak256(LM.encodeWithSaltAndBorrowerCounter(nlr.borrower, nlr.salt, keccak256(abi.encode(nlr.caveats))));
OfferItem[] memory offer = new OfferItem[](nlr.debt.length + 1);

for (uint256 i; i < debt.length;) {
Expand Down
19 changes: 19 additions & 0 deletions test/TestUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,30 @@ import {StarPortLib} from "starport-core/lib/StarPortLib.sol";

contract TestStarLiteUtils is Test {
TestContract testContract;
mapping(address => mapping(bytes32 => bool)) usedSalts;

function setUp() public {
testContract = new TestContract();
}

function testValidateSaltRef(address user, bytes32 salt) public {
StarPortLib.validateSaltRef(usedSalts, user, salt);

assert(usedSalts[user][salt]);
vm.expectRevert(abi.encodeWithSelector(StarPortLib.InvalidSalt.selector));

StarPortLib.validateSaltRef(usedSalts, user, salt);
}

function testValidateSaltOpt(address user, bytes32 salt) public {
StarPortLib.validateSalt(usedSalts, user, salt);

assert(usedSalts[user][salt]);

vm.expectRevert(abi.encodeWithSelector(StarPortLib.InvalidSalt.selector));
StarPortLib.validateSalt(usedSalts, user, salt);
}

function testSpentToReceived() public {
SpentItem[] memory spentItems = new SpentItem[](2);
spentItems[0] = SpentItem({itemType: ItemType.ERC20, token: address(2), identifier: 3, amount: 4});
Expand Down

0 comments on commit 75999cc

Please sign in to comment.