-
Notifications
You must be signed in to change notification settings - Fork 6
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
6e40348
commit 4028e76
Showing
7 changed files
with
490 additions
and
5 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
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,34 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.24; | ||
|
||
//interfaces | ||
|
||
//libraries | ||
|
||
//contracts | ||
import {Deployer} from "contracts/scripts/common/Deployer.s.sol"; | ||
import {TippingFacet} from "contracts/src/spaces/facets/tipping/TippingFacet.sol"; | ||
import {FacetHelper} from "contracts/test/diamond/Facet.t.sol"; | ||
|
||
contract DeployTipping is FacetHelper, Deployer { | ||
constructor() { | ||
addSelector(TippingFacet.tip.selector); | ||
addSelector(TippingFacet.tipsByCurrencyAndTokenId.selector); | ||
addSelector(TippingFacet.tippingCurrencies.selector); | ||
} | ||
|
||
function initializer() public pure override returns (bytes4) { | ||
return TippingFacet.__Tipping_init.selector; | ||
} | ||
|
||
function versionName() public pure override returns (string memory) { | ||
return "tippingFacet"; | ||
} | ||
|
||
function __deploy(address deployer) public override returns (address) { | ||
vm.startBroadcast(deployer); | ||
TippingFacet tipping = new TippingFacet(); | ||
vm.stopBroadcast(); | ||
return address(tipping); | ||
} | ||
} |
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
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,69 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
// interfaces | ||
|
||
// libraries | ||
|
||
// contracts | ||
|
||
interface ITippingBase { | ||
// ============================================================= | ||
// Structs | ||
// ============================================================= | ||
|
||
struct TipRequest { | ||
uint256 tokenId; | ||
address currency; | ||
uint256 amount; | ||
bytes32 messageId; | ||
bytes32 channelId; | ||
} | ||
|
||
// ============================================================= | ||
// Events | ||
// ============================================================= | ||
|
||
event Tip( | ||
uint256 indexed tokenId, | ||
address indexed currency, | ||
address sender, | ||
address receiver, | ||
uint256 amount | ||
); | ||
|
||
event TipMessage(bytes32 indexed messageId, bytes32 indexed channelId); | ||
|
||
// ============================================================= | ||
// Errors | ||
// ============================================================= | ||
|
||
error TokenDoesNotExist(); | ||
error SenderIsNotMember(); | ||
error ReceiverIsNotMember(); | ||
error CannotTipSelf(); | ||
error AmountIsZero(); | ||
error CurrencyIsZero(); | ||
} | ||
|
||
interface ITipping is ITippingBase { | ||
/// @notice Sends a tip to a space member | ||
/// @param tipRequest The tip request containing token ID, currency, amount, message ID and channel ID | ||
/// @dev Requires sender and receiver to be members of the space | ||
/// @dev Requires amount > 0 and valid currency address | ||
/// @dev Emits Tip and TipMessage events | ||
function tip(TipRequest calldata tipRequest) external payable; | ||
|
||
/// @notice Gets the total tips received for a token ID in a specific currency | ||
/// @param tokenId The token ID to get tips for | ||
/// @param currency The currency address to get tips in | ||
/// @return The total amount of tips received in the specified currency | ||
function tipsByCurrencyAndTokenId( | ||
uint256 tokenId, | ||
address currency | ||
) external view returns (uint256); | ||
|
||
/// @notice Gets the list of currencies that have been tipped to the space | ||
/// @return An array of currency addresses | ||
function tippingCurrencies() external view returns (address[] memory); | ||
} |
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,54 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
// interfaces | ||
|
||
// libraries | ||
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; | ||
import {CurrencyTransfer} from "contracts/src/utils/libraries/CurrencyTransfer.sol"; | ||
// contracts | ||
|
||
library TippingBase { | ||
using EnumerableSet for EnumerableSet.AddressSet; | ||
|
||
// keccak256(abi.encode(uint256(keccak256("spaces.facets.tipping.storage")) - 1)) & ~bytes32(uint256(0xff)) | ||
bytes32 internal constant STORAGE_SLOT = | ||
0xb6cb334a9eea0cca2581db4520b45ac6f03de8e3927292302206bb82168be300; | ||
|
||
struct Layout { | ||
EnumerableSet.AddressSet currencies; | ||
mapping(uint256 tokenId => mapping(address currency => uint256 amount)) tipsByCurrencyByTokenId; | ||
} | ||
|
||
function layout() internal pure returns (Layout storage l) { | ||
assembly { | ||
l.slot := STORAGE_SLOT | ||
} | ||
} | ||
|
||
function tip( | ||
address sender, | ||
address receiver, | ||
uint256 tokenId, | ||
address currency, | ||
uint256 amount | ||
) internal { | ||
Layout storage ds = layout(); | ||
|
||
ds.currencies.add(currency); | ||
ds.tipsByCurrencyByTokenId[tokenId][currency] += amount; | ||
|
||
CurrencyTransfer.transferCurrency(currency, sender, receiver, amount); | ||
} | ||
|
||
function tipsByCurrencyByTokenId( | ||
uint256 tokenId, | ||
address currency | ||
) internal view returns (uint256) { | ||
return layout().tipsByCurrencyByTokenId[tokenId][currency]; | ||
} | ||
|
||
function tippingCurrencies() internal view returns (address[] memory) { | ||
return layout().currencies.values(); | ||
} | ||
} |
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,80 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
// interfaces | ||
import {ITipping} from "./ITipping.sol"; | ||
|
||
// libraries | ||
import {TippingBase} from "./TippingBase.sol"; | ||
import {CustomRevert} from "contracts/src/utils/libraries/CustomRevert.sol"; | ||
|
||
// contracts | ||
import {ERC721ABase} from "contracts/src/diamond/facets/token/ERC721A/ERC721ABase.sol"; | ||
import {Facet} from "contracts/src/diamond/facets/Facet.sol"; | ||
|
||
contract TippingFacet is ITipping, ERC721ABase, Facet { | ||
function __Tipping_init() external onlyInitializing { | ||
_addInterface(type(ITipping).interfaceId); | ||
} | ||
|
||
/// @inheritdoc ITipping | ||
function tip(TipRequest calldata tipRequest) external payable { | ||
address receiver = _ownerOf(tipRequest.tokenId); | ||
|
||
_validateTipRequest( | ||
msg.sender, | ||
receiver, | ||
tipRequest.currency, | ||
tipRequest.amount | ||
); | ||
|
||
TippingBase.tip( | ||
msg.sender, | ||
receiver, | ||
tipRequest.tokenId, | ||
tipRequest.currency, | ||
tipRequest.amount | ||
); | ||
|
||
emit Tip( | ||
tipRequest.tokenId, | ||
tipRequest.currency, | ||
msg.sender, | ||
receiver, | ||
tipRequest.amount | ||
); | ||
|
||
emit TipMessage(tipRequest.messageId, tipRequest.channelId); | ||
} | ||
|
||
/// @inheritdoc ITipping | ||
function tippingCurrencies() external view returns (address[] memory) { | ||
return TippingBase.tippingCurrencies(); | ||
} | ||
|
||
/// @inheritdoc ITipping | ||
function tipsByCurrencyAndTokenId( | ||
uint256 tokenId, | ||
address currency | ||
) external view returns (uint256) { | ||
return TippingBase.tipsByCurrencyByTokenId(tokenId, currency); | ||
} | ||
|
||
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ | ||
/* Internal */ | ||
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ | ||
|
||
function _validateTipRequest( | ||
address sender, | ||
address receiver, | ||
address currency, | ||
uint256 amount | ||
) internal view { | ||
if (currency == address(0)) | ||
CustomRevert.revertWith(CurrencyIsZero.selector); | ||
if (sender == receiver) CustomRevert.revertWith(CannotTipSelf.selector); | ||
if (amount == 0) CustomRevert.revertWith(AmountIsZero.selector); | ||
if (_balanceOf(sender) == 0) | ||
CustomRevert.revertWith(SenderIsNotMember.selector); | ||
} | ||
} |
Oops, something went wrong.