Skip to content

Commit

Permalink
BaseContest improvements (#148)
Browse files Browse the repository at this point in the history
* let contest receive funds

* add payout splits helper functions

* add start time (does nothing) to contest

* test for timing

* Update .storage-layout

* new contest builder deployer
  • Loading branch information
rocketman-21 committed Apr 2, 2024
1 parent 2ea5e9e commit 3a13032
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilly-bats-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cobuild/revolution": patch
---

Make BaseContest payable and add payout splits helper functions
17 changes: 9 additions & 8 deletions packages/revolution/.storage-layout
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,15 @@
| WETH | address | 0 | 0 | 20 | src/culture-index/contests/BaseContest.sol:BaseContest |
| entropyRate | uint256 | 1 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| builderReward | address | 2 | 0 | 20 | src/culture-index/contests/BaseContest.sol:BaseContest |
| endTime | uint256 | 3 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| paidOut | bool | 4 | 0 | 1 | src/culture-index/contests/BaseContest.sol:BaseContest |
| payoutIndex | uint256 | 5 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| initialPayoutBalance | uint256 | 6 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| splitMain | contract ISplitMain | 7 | 0 | 20 | src/culture-index/contests/BaseContest.sol:BaseContest |
| cultureIndex | contract ICultureIndex | 8 | 0 | 20 | src/culture-index/contests/BaseContest.sol:BaseContest |
| payoutSplits | uint256[] | 9 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| payoutSplitAccounts | mapping(uint256 => address) | 10 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| startTime | uint256 | 3 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| endTime | uint256 | 4 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| paidOut | bool | 5 | 0 | 1 | src/culture-index/contests/BaseContest.sol:BaseContest |
| payoutIndex | uint256 | 6 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| initialPayoutBalance | uint256 | 7 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| splitMain | contract ISplitMain | 8 | 0 | 20 | src/culture-index/contests/BaseContest.sol:BaseContest |
| cultureIndex | contract ICultureIndex | 9 | 0 | 20 | src/culture-index/contests/BaseContest.sol:BaseContest |
| payoutSplits | uint256[] | 10 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |
| payoutSplitAccounts | mapping(uint256 => address) | 11 | 0 | 32 | src/culture-index/contests/BaseContest.sol:BaseContest |

=======================
➡ ContestBuilder
Expand Down
10 changes: 5 additions & 5 deletions packages/revolution/deploys/contests/84532.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Contest Builder: 0xd6e6635bb9dfd3a4bad698ea554bfbb373ad0fa6
Contest Builder implementation: 0xb50506c979bac7bcda3d27998e1c2faccc8942e0
Culture Index implementation: 0xa47e3accb7b271dc135e7490cf6dcd9de243499e
Max Heap implementation: 0xdfe840daddc5f00f5aaefd591938ad2cb90ef54a
Base Contest implementation: 0x1d3f513b0d4b9b6c0dbabdcfc74c392e5f8d1fd9
Contest Builder: 0x05a3910e27720aa220ddbcea8ab3fcdb2c66b768
Contest Builder implementation: 0xabbcb17afe77c694ec6739f0368f9b247da9963a
Culture Index implementation: 0x48121ad0212ee5c1b4885247910676a4ee5a500c
Max Heap implementation: 0x7582440dcf3e03c3d79a58bce1e99558125024f6
Base Contest implementation: 0x60f65632e4a448e33a07a4fa4b03f6daf5ec51e3
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ contract DeployContestBuilder is Script {
abi.encodePacked("Base Contest implementation: ", addressToString(deployedContracts.baseContestImpl))
)
);
// write protocol rewards address
vm.writeLine(
filePath,
string(abi.encodePacked("Protocol Rewards: ", addressToString(vm.envAddress("PROTOCOL_REWARDS"))))
);

console2.log("~~~~~~~~~~ MANAGER IMPL 0 ~~~~~~~~~~~");
console2.logAddress(deployedContracts.contestBuilderImpl0);
Expand Down
24 changes: 24 additions & 0 deletions packages/revolution/src/culture-index/contests/BaseContest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ contract BaseContest is
// The address of th account to receive builder rewards
address public builderReward;

// The start time of the contest
uint256 public startTime;

// The end time of the contest
uint256 public endTime;

Expand Down Expand Up @@ -158,6 +161,7 @@ contract BaseContest is

// set creator payout params
entropyRate = _baseContestParams.entropyRate;
startTime = _baseContestParams.startTime;
endTime = _baseContestParams.endTime;
payoutSplits = _baseContestParams.payoutSplits;
}
Expand Down Expand Up @@ -319,6 +323,22 @@ contract BaseContest is
return cultureIndex.topVotedPieceMeetsQuorum();
}

/**
* @notice Returns the payout splits of the contest
* @return The payout splits of the contest
*/
function getPayoutSplits() external view returns (uint256[] memory) {
return payoutSplits;
}

/**
* @notice Returns the payout splits count
* @return The payout splits count
*/
function getPayoutSplitsCount() external view returns (uint256) {
return payoutSplits.length;
}

/**
* @notice Pay out the contest winners
* @param _payoutCount The number of winners to pay out. Needs to be adjusted based on gas requirements.
Expand Down Expand Up @@ -383,6 +403,10 @@ contract BaseContest is
}
}

receive() external payable {}

fallback() external payable {}

/// ///
/// BASE CONTEST UPGRADE ///
/// ///
Expand Down
10 changes: 10 additions & 0 deletions packages/revolution/src/culture-index/contests/IBaseContest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,22 @@ interface IBaseContest is IBaseContestEvents {

function pause() external;

function getPayoutSplits() external view returns (uint256[] memory);

function getPayoutSplitsCount() external view returns (uint256);

function startTime() external view returns (uint256);

function endTime() external view returns (uint256);

/// @notice The contest parameters
/// @param entropyRate The entropy rate of each contest - the portion of the creator's share that is directly sent to the creator in ETH
/// @param endTime The end time of the contest.
/// @param startTime The start time of the contest.
/// @param payoutSplits How to split the prize pool between the winners
struct BaseContestParams {
uint256 entropyRate;
uint256 startTime;
uint256 endTime;
uint256[] payoutSplits;
}
Expand Down
5 changes: 4 additions & 1 deletion packages/revolution/test/contests/ContestBuilder.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ contract ContestBuilderTest is RevolutionBuilderTest {
payoutSplits[0] = 1e6;
baseContestParams = IBaseContest.BaseContestParams({
entropyRate: 100,
startTime: block.timestamp,
// 1 week
endTime: block.timestamp + 60 * 60 * 24 * 7,
payoutSplits: payoutSplits
Expand All @@ -144,11 +145,13 @@ contract ContestBuilderTest is RevolutionBuilderTest {

function setBaseContestParams(
uint256 _entropyRate,
uint256 _startTime,
uint256 _endTime,
uint256[] memory _payoutSplits
) internal virtual {
baseContestParams = IBaseContest.BaseContestParams({
entropyRate: _entropyRate,
startTime: _startTime,
endTime: _endTime,
payoutSplits: _payoutSplits
});
Expand Down Expand Up @@ -191,7 +194,7 @@ contract ContestBuilderTest is RevolutionBuilderTest {
_baseContestParams
);

baseContest = BaseContest(baseContestAddr);
baseContest = BaseContest(payable(baseContestAddr));
contest_CultureIndex = CultureIndex(address(baseContest.cultureIndex()));

vm.label(address(baseContest), "BASE_CONTEST");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ contract ContestOwnerControl is ContestBuilderTest {
);

// ensure founder can set entropyRateBps and that it is updated
BaseContest baseContest = BaseContest(contest);
BaseContest baseContest = BaseContest(payable(contest));
uint256 newEntropyRate = 51000; // Example new entropy rate to test with

// Ensure only the owner can set the entropy rate
Expand Down
10 changes: 5 additions & 5 deletions packages/revolution/test/contests/ContestPayouts.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ contract ContestOwnerControl is ContestBuilderTest {
payoutSplits[1] = 300000; // 30%
payoutSplits[2] = 200000; // 20%

super.setBaseContestParams(500000, block.timestamp + 60 * 60 * 24 * 7, payoutSplits);
super.setBaseContestParams(500000, block.timestamp, block.timestamp + 60 * 60 * 24 * 7, payoutSplits);

super.deployContestMock();
vm.stopPrank();
Expand Down Expand Up @@ -174,7 +174,7 @@ contract ContestOwnerControl is ContestBuilderTest {
payoutSplits[1] = 300000; // 30%
payoutSplits[2] = 200000; // 20%

super.setBaseContestParams(500000, block.timestamp + 60 * 60 * 24 * 7, payoutSplits);
super.setBaseContestParams(500000, block.timestamp, block.timestamp + 60 * 60 * 24 * 7, payoutSplits);

super.deployContestMock();
vm.stopPrank();
Expand Down Expand Up @@ -323,7 +323,7 @@ contract ContestOwnerControl is ContestBuilderTest {
payoutSplits[1] = 300000; // 30%
payoutSplits[2] = 200000; // 20%

super.setBaseContestParams(500000, block.timestamp + 60 * 60 * 24 * 7, payoutSplits);
super.setBaseContestParams(500000, block.timestamp, block.timestamp + 60 * 60 * 24 * 7, payoutSplits);

super.deployContestMock();
vm.stopPrank();
Expand Down Expand Up @@ -358,7 +358,7 @@ contract ContestOwnerControl is ContestBuilderTest {
// Scaled by 1e6
payoutSplits[0] = 1e6; // 50%

super.setBaseContestParams(500000, block.timestamp + 60 * 60 * 24 * 7, payoutSplits);
super.setBaseContestParams(500000, block.timestamp, block.timestamp + 60 * 60 * 24 * 7, payoutSplits);

super.deployContestMock();
vm.stopPrank();
Expand Down Expand Up @@ -421,7 +421,7 @@ contract ContestOwnerControl is ContestBuilderTest {
payoutSplits[i] = 100000; // 10% for each
}

super.setBaseContestParams(500000, block.timestamp + 60 * 60 * 24 * 7, payoutSplits);
super.setBaseContestParams(500000, block.timestamp, block.timestamp + 60 * 60 * 24 * 7, payoutSplits);

super.deployContestMock();

Expand Down
41 changes: 40 additions & 1 deletion packages/revolution/test/contests/ContestsCreation.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ contract ContestsCreationTest is ContestBuilderTest {
super.deployContestMock();
}

/**
* @dev Ensure the contest can be sent funds
*/
function test__SendFundsToContest() public {
// Send funds to the contest
uint256 amount = 1 ether;
vm.deal(address(this), amount);
vm.prank(address(this));
payable(address(baseContest)).call{ value: amount }(new bytes(0));

// Verify the balance of the contest
uint256 expectedBalance = amount;
uint256 actualBalance = address(baseContest).balance;
assertEq(actualBalance, expectedBalance, "Balance mismatch");
}

/**
* @dev Use the builder to create a contest and test the fields
*/
Expand All @@ -38,7 +54,7 @@ contract ContestsCreationTest is ContestBuilderTest {
);

// verify contest fields
BaseContest baseContest = BaseContest(contest);
BaseContest baseContest = BaseContest(payable(contest));
assertEq(baseContest.owner(), founder, "Owner mismatch");
assertEq(baseContest.WETH(), weth, "WETH mismatch");
assertEq(address(baseContest.splitMain()), address(splitMain), "Split main mismatch");
Expand Down Expand Up @@ -82,6 +98,23 @@ contract ContestsCreationTest is ContestBuilderTest {
contest_CultureIndexParams.description,
"CultureIndex description mismatch"
);

// ensure start time is set
uint256 expectedStartTime = baseContestParams.startTime;
uint256 actualStartTime = baseContest.startTime();
assertEq(actualStartTime, expectedStartTime, "Start time mismatch");

// ensure getPayoutSplitsCount returns the correct value
uint256 expectedPayoutSplitsCount = baseContestParams.payoutSplits.length;
uint256 actualPayoutSplitsCount = baseContest.getPayoutSplitsCount();
assertEq(actualPayoutSplitsCount, expectedPayoutSplitsCount, "Payout splits count mismatch");

// ensure getPayoutSplits returns the correct values
uint256[] memory expectedPayoutSplits = baseContestParams.payoutSplits;
uint256[] memory actualPayoutSplits = baseContest.getPayoutSplits();
for (uint256 i = 0; i < expectedPayoutSplits.length; i++) {
assertEq(actualPayoutSplits[i], expectedPayoutSplits[i], "Payout splits mismatch at index");
}
}

/**
Expand All @@ -107,6 +140,12 @@ contract ContestsCreationTest is ContestBuilderTest {
uint256 expectedEndTime = baseContestParams.endTime;
uint256 actualEndTime = baseContest.endTime();
assertTrue(actualEndTime == expectedEndTime, "End time mismatch");

// Verify the startTime of the deployed contest
uint256 expectedStartTime = baseContestParams.startTime;
uint256 actualStartTime = baseContest.startTime();
assertTrue(actualStartTime == expectedStartTime, "Start time mismatch");

// Verify the payoutSplits of the deployed contest
uint256[] memory expectedPayoutSplits = baseContestParams.payoutSplits;
for (uint256 i = 0; i < expectedPayoutSplits.length; i++) {
Expand Down

0 comments on commit 3a13032

Please sign in to comment.