Skip to content

Commit

Permalink
feat(curation-vault): impl CurationVault
Browse files Browse the repository at this point in the history
  • Loading branch information
gitwoz committed Nov 22, 2024
1 parent 575e615 commit 7182ee6
Show file tree
Hide file tree
Showing 11 changed files with 531 additions and 42 deletions.
2 changes: 2 additions & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ THESPACE_LP_TOKENS=
BILLBOARD_CURRENCY_TOKEN=
BILLBOARD_REGISTRY_ADDRESS=0x0000000000000000000000000000000000000000
BILLBOARD_ADMIN_ADDRESS=
CURATION_VAULT_SIGNER=
CURATION_VAULT_OWNER=
2 changes: 2 additions & 0 deletions .env.op-mainnet.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ THESPACE_LP_TOKENS=
BILLBOARD_CURRENCY_TOKEN=
BILLBOARD_REGISTRY_ADDRESS=0x0000000000000000000000000000000000000000
BILLBOARD_ADMIN_ADDRESS=
CURATION_VAULT_SIGNER=
CURATION_VAULT_OWNER=
2 changes: 2 additions & 0 deletions .env.op-sepolia.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ THESPACE_LP_TOKENS=
BILLBOARD_CURRENCY_TOKEN=
BILLBOARD_REGISTRY_ADDRESS=0x0000000000000000000000000000000000000000
BILLBOARD_ADMIN_ADDRESS=
CURATION_VAULT_SIGNER=
CURATION_VAULT_OWNER=
2 changes: 2 additions & 0 deletions .env.polygon-mainnet.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ THESPACE_LP_TOKENS=
BILLBOARD_CURRENCY_TOKEN=
BILLBOARD_REGISTRY_ADDRESS=0x0000000000000000000000000000000000000000
BILLBOARD_ADMIN_ADDRESS=
CURATION_VAULT_SIGNER=
CURATION_VAULT_OWNER=
2 changes: 2 additions & 0 deletions .env.polygon-mumbai.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ THESPACE_LP_TOKENS=
BILLBOARD_CURRENCY_TOKEN=0x0FA8781a83E46826621b3BC094Ea2A0212e71B23
BILLBOARD_REGISTRY_ADDRESS=0x0000000000000000000000000000000000000000
BILLBOARD_ADMIN_ADDRESS=
CURATION_VAULT_SIGNER=
CURATION_VAULT_OWNER=
68 changes: 41 additions & 27 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,25 @@ BillboardTest:testCannotSetWhitelistByAttacker() (gas: 228664)
BillboardTest:testCannotTransferByOperator() (gas: 226771)
BillboardTest:testCannotTransferToZeroAddress() (gas: 222258)
BillboardTest:testCannotUpgradeRegistryByAttacker() (gas: 9017)
BillboardTest:testCannotWithdrawBidIfAuctionNotEndedOrCleared(uint96) (runs: 256, μ: 632850, ~: 632850)
BillboardTest:testCannotWithdrawBidIfNotFound(uint96) (runs: 256, μ: 750346, ~: 750346)
BillboardTest:testCannotWithdrawBidIfWon(uint96) (runs: 256, μ: 1026516, ~: 1026516)
BillboardTest:testCannotWithdrawBidTwice(uint96) (runs: 256, μ: 1111002, ~: 1111002)
BillboardTest:testClearAuction(uint96) (runs: 256, μ: 731815, ~: 731815)
BillboardTest:testCannotWithdrawBidIfAuctionNotEndedOrCleared(uint96) (runs: 257, μ: 632850, ~: 632850)
BillboardTest:testCannotWithdrawBidIfNotFound(uint96) (runs: 257, μ: 750346, ~: 750346)
BillboardTest:testCannotWithdrawBidIfWon(uint96) (runs: 257, μ: 1026516, ~: 1026516)
BillboardTest:testCannotWithdrawBidTwice(uint96) (runs: 257, μ: 1111002, ~: 1111002)
BillboardTest:testClearAuction(uint96) (runs: 257, μ: 731815, ~: 731815)
BillboardTest:testClearAuctionIfAlreadyCleared() (gas: 738895)
BillboardTest:testClearAuctions() (gas: 1315317)
BillboardTest:testClearLastAuction(uint96) (runs: 256, μ: 732739, ~: 732739)
BillboardTest:testClearLastAuction(uint96) (runs: 257, μ: 732739, ~: 732739)
BillboardTest:testClearLastAuctions() (gas: 1332619)
BillboardTest:testGetBidderBids(uint8,uint8,uint8) (runs: 256, μ: 1508601, ~: 1140537)
BillboardTest:testGetBids(uint8,uint8,uint8) (runs: 256, μ: 8312589, ~: 6311372)
BillboardTest:testGetBlockFromEpoch() (gas: 16893)
BillboardTest:testGetEpochFromBlock() (gas: 17903)
BillboardTest:testGetTokenURI() (gas: 391345)
BillboardTest:testMintBoard() (gas: 585666)
BillboardTest:testPlaceBid(uint96) (runs: 256, μ: 840080, ~: 840702)
BillboardTest:testPlaceBid(uint96) (runs: 257, μ: 840082, ~: 840702)
BillboardTest:testPlaceBidIfBoardWhitelistDisabled() (gas: 598166)
BillboardTest:testPlaceBidWithHigherPrice(uint96) (runs: 256, μ: 1011527, ~: 1011532)
BillboardTest:testPlaceBidWithSamePrices(uint96) (runs: 256, μ: 908843, ~: 909776)
BillboardTest:testPlaceBidWithHigherPrice(uint96) (runs: 257, μ: 1011527, ~: 1011532)
BillboardTest:testPlaceBidWithSamePrices(uint96) (runs: 257, μ: 908846, ~: 909776)
BillboardTest:testPlaceBidZeroPrice() (gas: 432705)
BillboardTest:testSafeTransferByOperator() (gas: 235259)
BillboardTest:testSetBidURIs() (gas: 659834)
Expand All @@ -57,9 +57,9 @@ BillboardTest:testSetBoardWhitelistDisabled() (gas: 244401)
BillboardTest:testSetClosed() (gas: 241110)
BillboardTest:testSetWhitelist() (gas: 245426)
BillboardTest:testUpgradeRegistry() (gas: 3924811)
BillboardTest:testWithdrawBid(uint96) (runs: 256, μ: 1098966, ~: 1098966)
BillboardTest:testWithdrawBidIfClosed(uint96) (runs: 256, μ: 697036, ~: 697036)
BillboardTest:testWithdrawTax(uint96) (runs: 256, μ: 737116, ~: 737116)
BillboardTest:testWithdrawBid(uint96) (runs: 257, μ: 1098966, ~: 1098966)
BillboardTest:testWithdrawBidIfClosed(uint96) (runs: 257, μ: 697036, ~: 697036)
BillboardTest:testWithdrawTax(uint96) (runs: 257, μ: 737116, ~: 737116)
CurationTest:testCannotCurateERC20CurateZeroAmount() (gas: 12194)
CurationTest:testCannotCurateERC20EmptyURI() (gas: 15797)
CurationTest:testCannotCurateERC20IfNotApproval() (gas: 21624)
Expand All @@ -77,8 +77,8 @@ DistributionTest:testCannotClaimIfAlreadyClaimed() (gas: 284835)
DistributionTest:testCannotClaimIfInsufficientBalance() (gas: 394264)
DistributionTest:testCannotClaimIfInvalidProof() (gas: 245236)
DistributionTest:testCannotClaimIfInvalidTreeId() (gas: 243332)
DistributionTest:testCannotDropIfInsufficientAllowance(uint256) (runs: 256, μ: 212269, ~: 212284)
DistributionTest:testCannotDropIfInsufficientBalance(uint256) (runs: 256, μ: 214708, ~: 214740)
DistributionTest:testCannotDropIfInsufficientAllowance(uint256) (runs: 257, μ: 212269, ~: 212283)
DistributionTest:testCannotDropIfInsufficientBalance(uint256) (runs: 257, μ: 214708, ~: 214740)
DistributionTest:testCannotDropIfZeroAmount() (gas: 148793)
DistributionTest:testCannotDropTwiceWithSameTreeId() (gas: 307260)
DistributionTest:testCannotSetAdminByAdmin() (gas: 17334)
Expand All @@ -89,16 +89,16 @@ DistributionTest:testClaim() (gas: 414576)
DistributionTest:testDrop() (gas: 568791)
DistributionTest:testSetAdmin() (gas: 20239)
DistributionTest:testSweep() (gas: 253087)
LogbookNFTSVGTest:testTokenURI(uint8,uint8,uint16) (runs: 256, μ: 2613180, ~: 1746428)
LogbookNFTSVGTest:testTokenURI(uint8,uint8,uint16) (runs: 257, μ: 2619845, ~: 1746470)
LogbookTest:testClaim() (gas: 135608)
LogbookTest:testDonate(uint96) (runs: 256, μ: 156549, ~: 156936)
LogbookTest:testDonateWithCommission(uint96,uint96) (runs: 256, μ: 146644, ~: 140444)
LogbookTest:testFork(uint96,string) (runs: 256, μ: 452537, ~: 453928)
LogbookTest:testForkRecursively(uint8,uint96) (runs: 256, μ: 5351224, ~: 1801537)
LogbookTest:testForkWithCommission(uint96,string,uint256) (runs: 256, μ: 342465, ~: 257636)
LogbookTest:testDonate(uint96) (runs: 257, μ: 156550, ~: 156936)
LogbookTest:testDonateWithCommission(uint96,uint96) (runs: 257, μ: 146785, ~: 140444)
LogbookTest:testFork(uint96,string) (runs: 257, μ: 452546, ~: 453928)
LogbookTest:testForkRecursively(uint8,uint96) (runs: 257, μ: 5369772, ~: 1801537)
LogbookTest:testForkWithCommission(uint96,string,uint256) (runs: 257, μ: 342135, ~: 257636)
LogbookTest:testMulticall() (gas: 284999)
LogbookTest:testPublicSale() (gas: 207337)
LogbookTest:testPublish(string) (runs: 256, μ: 264065, ~: 263590)
LogbookTest:testPublish(string) (runs: 257, μ: 264063, ~: 263590)
LogbookTest:testPublishEn1000() (gas: 243477)
LogbookTest:testPublishEn140() (gas: 221241)
LogbookTest:testPublishEn200() (gas: 222826)
Expand All @@ -117,18 +117,18 @@ LogbookTest:testPublishZh5000() (gas: 607690)
LogbookTest:testSetDescription() (gas: 140760)
LogbookTest:testSetForkPrice() (gas: 153925)
LogbookTest:testSetTitle() (gas: 168680)
LogbookTest:testSplitRoyalty(uint8,uint8,uint96) (runs: 256, μ: 1959072, ~: 965338)
LogbookTest:testSplitRoyalty(uint8,uint8,uint96) (runs: 257, μ: 1969363, ~: 965338)
LogbookTest:testWithdraw() (gas: 7284400)
SnapperTest:testCannotInitRegionByNotOwner() (gas: 11365)
SnapperTest:testCannotReInitRegion() (gas: 14373)
SnapperTest:testCannotTakeSnapshotBeforeInit() (gas: 15717)
SnapperTest:testCannotTakeSnapshotByNotOwner() (gas: 12478)
SnapperTest:testCannotTakeSnapshotWrongLastBlock() (gas: 49242)
SnapperTest:testCannotTakeSnapshotWrongSnapshotBlock() (gas: 23899)
SnapperTest:testInitRegion(uint256) (runs: 256, μ: 114408, ~: 114408)
SnapperTest:testInitRegion(uint256) (runs: 257, μ: 114408, ~: 114408)
SnapperTest:testTakeSnapshot() (gas: 47831)
TheSpaceTest:testBatchBid() (gas: 695308)
TheSpaceTest:testBatchSetPixels(uint16,uint8) (runs: 256, μ: 371399, ~: 372904)
TheSpaceTest:testBatchSetPixels(uint16,uint8) (runs: 257, μ: 371405, ~: 372904)
TheSpaceTest:testBidDefaultedToken() (gas: 413399)
TheSpaceTest:testBidExistingToken() (gas: 360023)
TheSpaceTest:testBidNewToken() (gas: 303729)
Expand Down Expand Up @@ -165,16 +165,30 @@ TheSpaceTest:testSetColor() (gas: 331348)
TheSpaceTest:testSetMintTax() (gas: 271715)
TheSpaceTest:testSetPixel(uint256) (runs: 256, μ: 403816, ~: 403816)
TheSpaceTest:testSetPrice(uint256) (runs: 256, μ: 304652, ~: 304652)
TheSpaceTest:testSetPriceByOperator(uint96) (runs: 256, μ: 354785, ~: 354785)
TheSpaceTest:testSetPriceByOperator(uint96) (runs: 257, μ: 354785, ~: 354785)
TheSpaceTest:testSetPriceTooHigh() (gas: 314504)
TheSpaceTest:testSetTaxRate() (gas: 347951)
TheSpaceTest:testSetTokenImageURI() (gas: 355813)
TheSpaceTest:testSetTotalSupply(uint256) (runs: 256, μ: 352202, ~: 352208)
TheSpaceTest:testSetTotalSupply(uint256) (runs: 257, μ: 352202, ~: 352208)
TheSpaceTest:testSetTreasuryShare() (gas: 384288)
TheSpaceTest:testSettleTax() (gas: 339465)
TheSpaceTest:testTaxCalculation() (gas: 402405)
TheSpaceTest:testTokenShouldBeDefaulted() (gas: 325529)
TheSpaceTest:testTotalSupply() (gas: 7613)
TheSpaceTest:testUpgradeTo() (gas: 3215197)
TheSpaceTest:testWithdrawTreasury() (gas: 355172)
TheSpaceTest:testWithdrawUBI() (gas: 378319)
TheSpaceTest:testWithdrawUBI() (gas: 378319)
VaultTest:testCannotCurationInvalidURI() (gas: 12033)
VaultTest:testCannotCurationZeroAmount() (gas: 12358)
VaultTest:testCannotCurationZeroNativeAmount() (gas: 10004)
VaultTest:testCannotSetZeroSigner() (gas: 11066)
VaultTest:testCannotWithdrawAlreadyWithdrawn() (gas: 100199)
VaultTest:testCannotWithdrawExpired() (gas: 13075)
VaultTest:testCannotWithdrawInvalidSignature() (gas: 40010)
VaultTest:testCannotWithdrawZeroAddress() (gas: 11663)
VaultTest:testCannotWithdrawZeroAmount() (gas: 44392)
VaultTest:testERC20Curation(uint256) (runs: 256, μ: 81202, ~: 81202)
VaultTest:testERC20Withdrawal(uint256) (runs: 256, μ: 112216, ~: 112219)
VaultTest:testNativeCuration(uint256) (runs: 256, μ: 47876, ~: 47876)
VaultTest:testNativeWithdrawal(uint256) (runs: 256, μ: 98483, ~: 98483)
VaultTest:testSetSigner() (gas: 19504)
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ deploy-snapper: clean
deploy-curation: clean
@forge create Curation --rpc-url ${ETH_RPC_URL} --private-key ${DEPLOYER_PRIVATE_KEY} --legacy --verify --etherscan-api-key ${ETHERSCAN_API_KEY}

## Curation Vault
deploy-curation-vault: clean
@forge create CurationVault --rpc-url ${ETH_RPC_URL} --private-key ${DEPLOYER_PRIVATE_KEY} --constructor-args ${CURATION_VAULT_SIGNER} ${CURATION_VAULT_OWNER} --legacy --verify --etherscan-api-key ${ETHERSCAN_API_KEY}

## Billboard
deploy-billboard: clean
@forge create Billboard --rpc-url ${ETH_RPC_URL} --private-key ${DEPLOYER_PRIVATE_KEY} --constructor-args ${BILLBOARD_CURRENCY_TOKEN} ${BILLBOARD_REGISTRY_ADDRESS} ${BILLBOARD_ADMIN_ADDRESS} "Billboard" "BLBD" --legacy --verify --etherscan-api-key ${ETHERSCAN_API_KEY}
Expand Down
100 changes: 86 additions & 14 deletions src/Curation/IVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
* @notice CurationVault is the contract for off-chain content curation.
*
* Curate:
* - Any address (curator) can send native or ERC-20 tokens to domain-specific ID (content creator) to curate the specific content.
* - Any address (curator) can send native or ERC-20 tokens to domain-specific UID (content creator) to curate the specific content.
* - Tokens will be locked in the contract.
*
* Withdraw:
* - Contract owner can withdraw locked tokens to a given address.
*/
interface ICurationVault {
//////////////////////////////
/// Error types
//////////////////////////////

/**
* @notice Zero ID or address is invalid.
*/
Expand All @@ -40,75 +44,143 @@ interface ICurationVault {
*/
error InvalidSignature();

/**
* @notice expired.
*/
error Expired();

/**
* @notice Already withdrawn.
*/
error AlreadyWithdrawn();

//////////////////////////////
/// Event types
//////////////////////////////

/**
* @notice Content curation with ERC-20 token.
* @param from Address of content curator.
* @param to Domain-specific ID of content creator.
* @param uid Domain-specific ID of content creator.
* @param uri Content URI.
* @param token ERC20 token address.
* @param amount Amount of tokens to curate.
*/
event Curation(address indexed from, string indexed to, IERC20 indexed token, string uri, uint256 amount);
event Curation(address indexed from, string indexed uid, IERC20 indexed token, string uri, uint256 amount);

/**
* @notice Content curation with native token.
* @param from Address of content curator.
* @param to Domain-specific ID of content creator.
* @param uid Domain-specific ID of content creator.
* @param uri Content URI.
* @param amount Amount of tokens to curate.
*/
event Curation(address indexed from, string indexed to, string uri, uint256 amount);
event Curation(address indexed from, string indexed uid, string uri, uint256 amount);

/**
* @notice Native token withdrawal.
* @param to Address to withdraw tokens.
* @param uid Domain-specific ID of content creator.
* @param amount Amount of tokens to withdraw.
*/
event Withdraw(address indexed to, uint256 amount);
event Withdraw(address indexed to, string indexed uid, uint256 amount);

/**
* @notice ERC-20 token withdrawal.
* @param to Address to withdraw tokens.
* @param uid Domain-specific ID of content creator.
* @param token ERC20 token address.
* @param amount Amount of tokens to withdraw.
*/
event Withdraw(address indexed to, IERC20 indexed token, uint256 amount);
event Withdraw(address indexed to, string indexed uid, IERC20 indexed token, uint256 amount);

/**
* @notice Signer is changed.
* @param signer New signer of the contract.
*/
event SignerChanged(address indexed signer);

//////////////////////////////
/// Curate
//////////////////////////////

/**
* @notice Curate content by ERC-20 token donation.
*
* @dev Emits: {Curation} event.
* @dev Throws: {ZeroAddress}, {ZeroAmount}, {InvalidURI} error.
*
* @param to_ Domain-specific ID of content creator.
* @param uid_ Domain-specific ID of content creator.
* @param token_ ERC20 token address.
* @param amount_ Amount of tokens to curate.
* @param uri_ Content URI.
*/
function curate(string calldata to_, IERC20 token_, uint256 amount_, string calldata uri_) external;
function curate(string calldata uid_, IERC20 token_, uint256 amount_, string calldata uri_) external;

/**
* @notice Curate content by native token donation.
*
* @dev Emits: {Curation} event.
* @dev Throws: {ZeroAddress}, {ZeroAmount}, {InvalidURI} error.
*
* @param to_ Domain-specific ID of content creator.
* @param uid_ Domain-specific ID of content creator.
* @param uri_ Content URI.
*/
function curate(string calldata to_, string calldata uri_) external payable;
function curate(string calldata uid_, string calldata uri_) external payable;

//////////////////////////////
/// Withdraw
//////////////////////////////

/**
* @notice Withdraw locked ERC-20 tokens to a given address.
*
* @dev Emits: {Withdraw} event.
* @dev Throws: {ZeroAddress}, {TransferFailed}, {InvalidSignature} error.
*
* @param to_ Address to withdraw tokens.
* @param uid_ Domain-specific ID of content creator.
* @param token_ ERC20 token address.
* @param expiredAt_ Expiration timestamp.
* @param v_ ECDSA signature v.
* @param r_ ECDSA signature r.
* @param s_ ECDSA signature s.
*/
function withdraw(
address to_,
string calldata uid_,
IERC20 token_,
uint256 expiredAt_,
uint8 v_,
bytes32 r_,
bytes32 s_
) external;

/**
* @notice Withdraw locked tokens to a given address.
* @notice Withdraw locked native tokens to a given address.
*
* @dev Emits: {Withdraw} event.
* @dev Throws: {ZeroAddress}, {TransferFailed}, {InvalidSignature} error.
*
* @param to_ Address to withdraw tokens.
* @param hashedMessage_ Hashed message.
* @param uid_ Domain-specific ID of content creator.
* @param expiredAt_ Expiration timestamp.
* @param v_ ECDSA signature v.
* @param r_ ECDSA signature r.
* @param s_ ECDSA signature s.
*/
function withdraw(address to_, bytes32 hashedMessage_, uint8 v_, bytes32 r_, bytes32 s_) external;
function withdraw(address to_, string calldata uid_, uint256 expiredAt_, uint8 v_, bytes32 r_, bytes32 s_) external;

//////////////////////////////
/// Verify
//////////////////////////////

/**
* @notice Set a new signer for the contract
* @dev Emits: {SignerChanged} event.
* @dev Throws: {ZeroAddress} error.
*
* @param signer_ Address of the new signer.
*/
function setSigner(address signer_) external;
}
Loading

0 comments on commit 7182ee6

Please sign in to comment.