Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed function visibility to external #5

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 88 additions & 28 deletions src/EthRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,11 @@ contract EthRouter is ERC721TokenReceiver {
/// @param deadline The deadline for the transaction to be mined. Will revert if timestamp is greater than deadline.
/// If it's set to 0 then there is no deadline.
/// @param payRoyalties Whether to pay royalties or not.
function buy(Buy[] calldata buys, uint256 deadline, bool payRoyalties) public payable {
function buy(
Buy[] calldata buys,
uint256 deadline,
bool payRoyalties
) external payable {
// check that the deadline has not passed (if any)
if (block.timestamp > deadline && deadline != 0) {
revert DeadlinePassed();
Expand All @@ -106,17 +110,23 @@ contract EthRouter is ERC721TokenReceiver {
for (uint256 i = 0; i < buys.length; i++) {
if (buys[i].isPublicPool) {
// execute the buy against a public pool
uint256 inputAmount = Pair(buys[i].pool).nftBuy{value: buys[i].baseTokenAmount}(
buys[i].tokenIds, buys[i].baseTokenAmount, 0
);
uint256 inputAmount = Pair(buys[i].pool).nftBuy{
value: buys[i].baseTokenAmount
}(buys[i].tokenIds, buys[i].baseTokenAmount, 0);

// pay the royalties if buyer has opted-in
if (payRoyalties) {
uint256 salePrice = inputAmount / buys[i].tokenIds.length;
for (uint256 j = 0; j < buys[i].tokenIds.length; j++) {
// get the royalty fee and recipient
(uint256 royaltyFee, address royaltyRecipient) =
getRoyalty(buys[i].nft, buys[i].tokenIds[j], salePrice);
(
uint256 royaltyFee,
address royaltyRecipient
) = getRoyalty(
buys[i].nft,
buys[i].tokenIds[j],
salePrice
);

if (royaltyFee > 0) {
// transfer the royalty fee to the royalty recipient
Expand All @@ -127,13 +137,19 @@ contract EthRouter is ERC721TokenReceiver {
} else {
// execute the buy against a private pool
PrivatePool(buys[i].pool).buy{value: buys[i].baseTokenAmount}(
buys[i].tokenIds, buys[i].tokenWeights, buys[i].proof
buys[i].tokenIds,
buys[i].tokenWeights,
buys[i].proof
);
}

for (uint256 j = 0; j < buys[i].tokenIds.length; j++) {
// transfer the NFT to the caller
ERC721(buys[i].nft).safeTransferFrom(address(this), msg.sender, buys[i].tokenIds[j]);
ERC721(buys[i].nft).safeTransferFrom(
address(this),
msg.sender,
buys[i].tokenIds[j]
);
}
}

Expand All @@ -149,7 +165,12 @@ contract EthRouter is ERC721TokenReceiver {
/// @param deadline The deadline for the transaction to be mined. Will revert if timestamp is greater than deadline.
/// Set to 0 for there to be no deadline.
/// @param payRoyalties Whether to pay royalties or not.
function sell(Sell[] calldata sells, uint256 minOutputAmount, uint256 deadline, bool payRoyalties) public {
function sell(
Sell[] calldata sells,
uint256 minOutputAmount,
uint256 deadline,
bool payRoyalties
) external {
// check that the deadline has not passed (if any)
if (block.timestamp > deadline && deadline != 0) {
revert DeadlinePassed();
Expand All @@ -159,7 +180,11 @@ contract EthRouter is ERC721TokenReceiver {
for (uint256 i = 0; i < sells.length; i++) {
// transfer the NFTs into the router from the caller
for (uint256 j = 0; j < sells[i].tokenIds.length; j++) {
ERC721(sells[i].nft).safeTransferFrom(msg.sender, address(this), sells[i].tokenIds[j]);
ERC721(sells[i].nft).safeTransferFrom(
msg.sender,
address(this),
sells[i].tokenIds[j]
);
}

// approve the pair to transfer NFTs from the router
Expand All @@ -174,16 +199,25 @@ contract EthRouter is ERC721TokenReceiver {
sells[i].publicPoolProofs,
// ReservoirOracle.Message[] is the exact same as IStolenNftOracle.Message[] and can be
// decoded/encoded 1-to-1.
abi.decode(abi.encode(sells[i].stolenNftProofs), (ReservoirOracle.Message[]))
abi.decode(
abi.encode(sells[i].stolenNftProofs),
(ReservoirOracle.Message[])
)
);

// pay the royalties if seller has opted-in
if (payRoyalties) {
uint256 salePrice = outputAmount / sells[i].tokenIds.length;
for (uint256 j = 0; j < sells[i].tokenIds.length; j++) {
// get the royalty fee and recipient
(uint256 royaltyFee, address royaltyRecipient) =
getRoyalty(sells[i].nft, sells[i].tokenIds[j], salePrice);
(
uint256 royaltyFee,
address royaltyRecipient
) = getRoyalty(
sells[i].nft,
sells[i].tokenIds[j],
salePrice
);

if (royaltyFee > 0) {
// transfer the royalty fee to the royalty recipient
Expand All @@ -194,7 +228,10 @@ contract EthRouter is ERC721TokenReceiver {
} else {
// execute the sell against a private pool
PrivatePool(sells[i].pool).sell(
sells[i].tokenIds, sells[i].tokenWeights, sells[i].proof, sells[i].stolenNftProofs
sells[i].tokenIds,
sells[i].tokenWeights,
sells[i].proof,
sells[i].stolenNftProofs
);
}
}
Expand Down Expand Up @@ -223,7 +260,7 @@ contract EthRouter is ERC721TokenReceiver {
uint256 minPrice,
uint256 maxPrice,
uint256 deadline
) public payable {
) external payable {
// check deadline has not passed (if any)
if (block.timestamp > deadline && deadline != 0) {
revert DeadlinePassed();
Expand All @@ -237,7 +274,11 @@ contract EthRouter is ERC721TokenReceiver {

// transfer NFTs from caller
for (uint256 i = 0; i < tokenIds.length; i++) {
ERC721(nft).safeTransferFrom(msg.sender, address(this), tokenIds[i]);
ERC721(nft).safeTransferFrom(
msg.sender,
address(this),
tokenIds[i]
);
}

// approve pair to transfer NFTs from router
Expand All @@ -251,7 +292,10 @@ contract EthRouter is ERC721TokenReceiver {
/// @param changes The change operations to execute.
/// @param deadline The deadline for the transaction to be mined. Will revert if timestamp is greater than deadline.
/// Set to 0 for deadline to be ignored.
function change(Change[] calldata changes, uint256 deadline) public payable {
function change(
Change[] calldata changes,
uint256 deadline
) external payable {
// check deadline has not passed (if any)
if (block.timestamp > deadline && deadline != 0) {
revert DeadlinePassed();
Expand All @@ -263,7 +307,11 @@ contract EthRouter is ERC721TokenReceiver {

// transfer NFTs from caller
for (uint256 j = 0; j < changes[i].inputTokenIds.length; j++) {
ERC721(_change.nft).safeTransferFrom(msg.sender, address(this), _change.inputTokenIds[j]);
ERC721(_change.nft).safeTransferFrom(
msg.sender,
address(this),
_change.inputTokenIds[j]
);
}

// approve pair to transfer NFTs from router
Expand All @@ -282,7 +330,11 @@ contract EthRouter is ERC721TokenReceiver {

// transfer NFTs to caller
for (uint256 j = 0; j < changes[i].outputTokenIds.length; j++) {
ERC721(_change.nft).safeTransferFrom(address(this), msg.sender, _change.outputTokenIds[j]);
ERC721(_change.nft).safeTransferFrom(
address(this),
msg.sender,
_change.outputTokenIds[j]
);
}
}

Expand All @@ -298,17 +350,25 @@ contract EthRouter is ERC721TokenReceiver {
/// @param salePrice The sale price of the NFT.
/// @return royaltyFee The royalty fee to pay.
/// @return recipient The address to pay the royalty fee to.
function getRoyalty(address nft, uint256 tokenId, uint256 salePrice)
public
view
returns (uint256 royaltyFee, address recipient)
{
function getRoyalty(
address nft,
uint256 tokenId,
uint256 salePrice
) public view returns (uint256 royaltyFee, address recipient) {
// get the royalty lookup address
address lookupAddress = IRoyaltyRegistry(royaltyRegistry).getRoyaltyLookupAddress(nft);

if (IERC2981(lookupAddress).supportsInterface(type(IERC2981).interfaceId)) {
address lookupAddress = IRoyaltyRegistry(royaltyRegistry)
.getRoyaltyLookupAddress(nft);

if (
IERC2981(lookupAddress).supportsInterface(
type(IERC2981).interfaceId
)
) {
// get the royalty fee from the registry
(recipient, royaltyFee) = IERC2981(lookupAddress).royaltyInfo(tokenId, salePrice);
(recipient, royaltyFee) = IERC2981(lookupAddress).royaltyInfo(
tokenId,
salePrice
);

// revert if the royalty fee is greater than the sale price
if (royaltyFee > salePrice) revert InvalidRoyaltyFee();
Expand Down
46 changes: 35 additions & 11 deletions src/Factory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ contract Factory is ERC721, Owned {
using LibClone for address;
using SafeTransferLib for address;

event Create(address indexed privatePool, uint256[] tokenIds, uint256 baseTokenAmount);
event Create(
address indexed privatePool,
uint256[] tokenIds,
uint256 baseTokenAmount
);
event Withdraw(address indexed token, uint256 indexed amount);

/// @notice The address of the private pool implementation that proxies point to.
Expand Down Expand Up @@ -81,15 +85,20 @@ contract Factory is ERC721, Owned {
bytes32 _salt,
uint256[] memory tokenIds, // put in memory to avoid stack too deep error
uint256 baseTokenAmount
) public payable returns (PrivatePool privatePool) {
) external payable returns (PrivatePool privatePool) {
// check that the msg.value is equal to the base token amount if the base token is ETH or the msg.value is equal
// to zero if the base token is not ETH
if ((_baseToken == address(0) && msg.value != baseTokenAmount) || (_baseToken != address(0) && msg.value > 0)) {
if (
(_baseToken == address(0) && msg.value != baseTokenAmount) ||
(_baseToken != address(0) && msg.value > 0)
) {
revert PrivatePool.InvalidEthAmount();
}

// deploy a minimal proxy clone of the private pool implementation
privatePool = PrivatePool(payable(privatePoolImplementation.cloneDeterministic(_salt)));
privatePool = PrivatePool(
payable(privatePoolImplementation.cloneDeterministic(_salt))
);

// mint the nft to the caller
_safeMint(msg.sender, uint256(uint160(address(privatePool))));
Expand All @@ -112,12 +121,20 @@ contract Factory is ERC721, Owned {
address(privatePool).safeTransferETH(baseTokenAmount);
} else {
// deposit the base tokens from the caller into the pool
ERC20(_baseToken).transferFrom(msg.sender, address(privatePool), baseTokenAmount);
ERC20(_baseToken).transferFrom(
msg.sender,
address(privatePool),
baseTokenAmount
);
}

// deposit the nfts from the caller into the pool
for (uint256 i = 0; i < tokenIds.length; i++) {
ERC721(_nft).safeTransferFrom(msg.sender, address(privatePool), tokenIds[i]);
ERC721(_nft).safeTransferFrom(
msg.sender,
address(privatePool),
tokenIds[i]
);
}

// emit create event
Expand All @@ -126,13 +143,17 @@ contract Factory is ERC721, Owned {

/// @notice Sets private pool metadata contract.
/// @param _privatePoolMetadata The private pool metadata contract.
function setPrivatePoolMetadata(address _privatePoolMetadata) public onlyOwner {
function setPrivatePoolMetadata(
address _privatePoolMetadata
) public onlyOwner {
privatePoolMetadata = _privatePoolMetadata;
}

/// @notice Sets the private pool implementation contract that newly deployed proxies point to.
/// @param _privatePoolImplementation The private pool implementation contract.
function setPrivatePoolImplementation(address _privatePoolImplementation) public onlyOwner {
function setPrivatePoolImplementation(
address _privatePoolImplementation
) public onlyOwner {
privatePoolImplementation = _privatePoolImplementation;
}

Expand All @@ -145,7 +166,7 @@ contract Factory is ERC721, Owned {
/// @notice Withdraws the earned protocol fees.
/// @param token The token to withdraw.
/// @param amount The amount to withdraw.
function withdraw(address token, uint256 amount) public onlyOwner {
function withdraw(address token, uint256 amount) external onlyOwner {
if (token == address(0)) {
msg.sender.safeTransferETH(amount);
} else {
Expand All @@ -165,7 +186,10 @@ contract Factory is ERC721, Owned {
/// @notice Predicts the deployment address of a new private pool.
/// @param salt The salt that will used on deployment.
/// @return predictedAddress The predicted deployment address of the private pool.
function predictPoolDeploymentAddress(bytes32 salt) public view returns (address predictedAddress) {
predictedAddress = privatePoolImplementation.predictDeterministicAddress(salt, address(this));
function predictPoolDeploymentAddress(
bytes32 salt
) public view returns (address predictedAddress) {
predictedAddress = privatePoolImplementation
.predictDeterministicAddress(salt, address(this));
}
}
Loading