-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f013dd4
commit 739c10c
Showing
4 changed files
with
206 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
pragma solidity ^0.8.17; | ||
|
||
import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; | ||
|
||
import {LoanManager} from "starport-core/LoanManager.sol"; | ||
import "forge-std/console.sol"; | ||
|
||
enum Actions { | ||
Nothing, | ||
Origination, | ||
Refinance, | ||
Repayment, | ||
Settlement | ||
} | ||
|
||
library RefStarPortLib { | ||
error InvalidSalt(); | ||
|
||
uint256 internal constant ONE_WORD = 0x20; | ||
uint256 internal constant CUSTODIAN_WORD_OFFSET = 0x40; | ||
|
||
function getAction(bytes calldata data) internal pure returns (Actions action) { | ||
assembly { | ||
action := calldataload(data.offset) | ||
} | ||
} | ||
|
||
function getCustodian(bytes calldata data) internal pure returns (address custodian) { | ||
assembly { | ||
custodian := calldataload(add(data.offset, CUSTODIAN_WORD_OFFSET)) | ||
} | ||
} | ||
|
||
function toReceivedItems(SpentItem[] calldata spentItems, address recipient) | ||
internal | ||
pure | ||
returns (ReceivedItem[] memory consideration) | ||
{ | ||
consideration = new ReceivedItem[](spentItems.length); | ||
for (uint256 i = 0; i < spentItems.length;) { | ||
consideration[i] = ReceivedItem({ | ||
itemType: spentItems[i].itemType, | ||
token: spentItems[i].token, | ||
identifier: spentItems[i].identifier, | ||
amount: spentItems[i].amount, | ||
recipient: payable(recipient) | ||
}); | ||
unchecked { | ||
++i; | ||
} | ||
} | ||
} | ||
|
||
function validateSalt( | ||
mapping(address => mapping(bytes32 => bool)) storage usedSalts, | ||
address borrower, | ||
bytes32 salt | ||
) internal { | ||
if (usedSalts[borrower][salt]) { | ||
revert InvalidSalt(); | ||
} | ||
usedSalts[borrower][salt] = true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
140 changes: 140 additions & 0 deletions
140
test/fuzz-testing/differential-fuzzing/TestStarPortLib.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
pragma solidity =0.8.17; | ||
|
||
import "forge-std/Test.sol"; | ||
import {Vm} from "forge-std/Vm.sol"; | ||
|
||
import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; | ||
import { | ||
ConsiderationItem, | ||
AdvancedOrder, | ||
CriteriaResolver, | ||
OrderType | ||
} from "seaport-types/src/lib/ConsiderationStructs.sol"; | ||
import {Conduit} from "seaport-core/src/conduit/Conduit.sol"; | ||
import {ConduitController} from "seaport-core/src/conduit/ConduitController.sol"; | ||
import {StarPortLib} from "starport-core/lib/StarPortLib.sol"; | ||
import {RefStarPortLib} from "starport-core/lib/RefStarPortLib.sol"; | ||
import "starport-test/utils/FuzzStructs.sol" as Fuzz; | ||
import {Bound} from "starport-test/utils/Bound.sol"; | ||
import {DeepEq} from "starport-test/utils/DeepEq.sol"; | ||
|
||
contract DiffFuzzTestStarPortLib is Test, Bound, DeepEq { | ||
StarPortLibImpl testContract; | ||
RefStarPortLibImpl refContract; | ||
|
||
function setUp() public { | ||
testContract = new StarPortLibImpl(); | ||
refContract = new RefStarPortLibImpl(); | ||
} | ||
|
||
function testSpentToReceived(Fuzz.SpentItem[] memory unbSpentItems) public view { | ||
SpentItem[] memory spentItems = _boundSpentItems(unbSpentItems); | ||
|
||
ReceivedItem[] memory consideration0 = testContract.toReceivedItems(spentItems, address(1)); | ||
ReceivedItem[] memory consideration1 = refContract.toReceivedItems(spentItems, address(1)); | ||
|
||
_deepEq(consideration0, consideration1); | ||
} | ||
|
||
function testUnboundSpentToReceived(Fuzz.SpentItem[] memory unbSpentItems) public { | ||
console.log("testUnboundSpentToReceived"); | ||
(bool success,) = address(refContract).call( | ||
abi.encodeWithSelector(RefStarPortLibImpl.toReceivedItems.selector, unbSpentItems, address(1)) | ||
); | ||
bool expectRevert = !success; | ||
|
||
(success,) = address(testContract).call( | ||
abi.encodeWithSelector(StarPortLibImpl.toReceivedItems.selector, unbSpentItems, address(1)) | ||
); | ||
if (expectRevert) { | ||
assertTrue(!success, "expected revert"); | ||
} else { | ||
assertTrue(success, "expected success"); | ||
} | ||
} | ||
|
||
} | ||
|
||
abstract contract BaseTestStarPortLib is Test { | ||
StarPortLibImpl testContract; | ||
|
||
function _setUp(address testImpl) internal { | ||
testContract = StarPortLibImpl(testImpl); | ||
} | ||
|
||
function testValidateSalt(address user, bytes32 salt) public { | ||
testContract.validateSalt(user, salt); | ||
|
||
assert(testContract.usedSalts(user, salt)); | ||
|
||
vm.expectRevert(abi.encodeWithSelector(StarPortLib.InvalidSalt.selector)); | ||
testContract.validateSalt(user, salt); | ||
} | ||
|
||
function testSpentToReceived() public { | ||
SpentItem[] memory spentItems = new SpentItem[](2); | ||
spentItems[0] = SpentItem({itemType: ItemType.ERC20, token: address(2), identifier: 3, amount: 4}); | ||
|
||
spentItems[1] = SpentItem({itemType: ItemType.ERC20, token: address(2), identifier: 3, amount: 4}); | ||
|
||
address recipient = address(1); | ||
ReceivedItem[] memory consideration0 = testContract.toReceivedItems(spentItems, recipient); | ||
|
||
assertEq(consideration0.length, spentItems.length); | ||
for (uint256 i = 0; i < consideration0.length; i++) { | ||
assert(consideration0[i].itemType == spentItems[i].itemType); | ||
assertEq(consideration0[i].token, spentItems[i].token); | ||
assertEq(consideration0[i].identifier, spentItems[i].identifier); | ||
assertEq(consideration0[i].amount, spentItems[i].amount); | ||
assertEq(consideration0[i].recipient, recipient); | ||
} | ||
} | ||
} | ||
|
||
contract TestStarPortLib is BaseTestStarPortLib { | ||
function setUp() public { | ||
_setUp(address(new StarPortLibImpl())); | ||
} | ||
} | ||
|
||
contract TestRefStarPortLib is BaseTestStarPortLib { | ||
function setUp() public { | ||
_setUp(address(new RefStarPortLibImpl())); | ||
} | ||
} | ||
|
||
contract StarPortLibImpl { | ||
using RefStarPortLib for *; | ||
|
||
mapping(address => mapping(bytes32 => bool)) public usedSalts; | ||
|
||
function toReceivedItems(SpentItem[] calldata spentItems, address recipient) | ||
external | ||
pure | ||
returns (ReceivedItem[] memory consideration) | ||
{ | ||
return spentItems.toReceivedItems(recipient); | ||
} | ||
|
||
function validateSalt(address user, bytes32 salt) external { | ||
usedSalts.validateSalt(user, salt); | ||
} | ||
} | ||
|
||
contract RefStarPortLibImpl { | ||
using RefStarPortLib for *; | ||
|
||
mapping(address => mapping(bytes32 => bool)) public usedSalts; | ||
|
||
function toReceivedItems(SpentItem[] calldata spentItems, address recipient) | ||
external | ||
pure | ||
returns (ReceivedItem[] memory consideration) | ||
{ | ||
return spentItems.toReceivedItems(recipient); | ||
} | ||
|
||
function validateSalt(address user, bytes32 salt) external { | ||
usedSalts.validateSalt(user, salt); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.