Skip to content
This repository has been archived by the owner on Apr 22, 2024. It is now read-only.

Commit

Permalink
Merge pull request #76 from factchain/improve-contracts
Browse files Browse the repository at this point in the history
Improve contracts
  • Loading branch information
YBadiss authored Feb 11, 2024
2 parents 5201fc7 + c5de011 commit 64a1739
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 138 deletions.
46 changes: 28 additions & 18 deletions fc-community-contracts/src/FactchainCommunity.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ interface IFactchainCommunity is IFactchainCommunityEvents {
contract FactchainCommunity is Ownable, IFactchainCommunity {
uint8 internal constant POST_URL_MAX_LENGTH = 160;
uint16 internal constant CONTENT_MAX_LENGTH = 500;
uint16 internal constant MINIMUM_STAKE_PER_RATING = 10_000;
uint32 internal constant MINIMUM_STAKE_PER_NOTE = 100_000;
uint64 public minimumStakePerNote = 1_000_000_000_000_000;
uint64 public minimumStakePerRating = 100_000_000_000_000;

/// @notice Mapping of note identifier (postUrl + creatorAddress) to Note object
mapping(string => mapping(address => Note)) public communityNotes;
Expand Down Expand Up @@ -138,21 +138,21 @@ contract FactchainCommunity is Ownable, IFactchainCommunity {
if (finalRating >= 3) {
uint96 reward = uint96(finalRating - 2) * 10;
// This will revert if contract current balance
// (address(this).balance) < MINIMUM_STAKE_PER_NOTE + reward
(bool result,) = payable(_creator).call{value: MINIMUM_STAKE_PER_NOTE + reward}("");
// (address(this).balance) < minimumStakePerNote + reward
(bool result,) = payable(_creator).call{value: minimumStakePerNote + reward}("");
if (!result) revert FailedToReward();

userStats[_creator].ethRewarded += reward;
emit CreatorRewarded({postUrl: _postUrl, creator: _creator, reward: reward, stake: MINIMUM_STAKE_PER_NOTE});
emit CreatorRewarded({postUrl: _postUrl, creator: _creator, reward: reward, stake: minimumStakePerNote});
} else if (finalRating < 2) {
uint96 slash = finalRating * 10;
// This will revert if contract current balance
// (address(this).balance) < MINIMUM_STAKE_PER_NOTE - slash
(bool result,) = payable(_creator).call{value: MINIMUM_STAKE_PER_NOTE - slash}("");
// (address(this).balance) < minimumStakePerNote - slash
(bool result,) = payable(_creator).call{value: minimumStakePerNote - slash}("");
if (!result) revert FailedToSlash();

userStats[_creator].ethSlashed += slash;
emit CreatorSlashed({postUrl: _postUrl, creator: _creator, slash: slash, stake: MINIMUM_STAKE_PER_NOTE});
emit CreatorSlashed({postUrl: _postUrl, creator: _creator, slash: slash, stake: minimumStakePerNote});
}
}

Expand All @@ -164,8 +164,8 @@ contract FactchainCommunity is Ownable, IFactchainCommunity {
if (delta < 2) {
uint96 reward = 2 - delta;
// This will revert if contract current balance
// (address(this).balance) < MINIMUM_STAKE_PER_RATING + reward
(bool result,) = payable(rater).call{value: MINIMUM_STAKE_PER_RATING + reward}("");
// (address(this).balance) < minimumStakePerRating + reward
(bool result,) = payable(rater).call{value: minimumStakePerRating + reward}("");
if (!result) revert FailedToReward();

userStats[rater].ethRewarded += reward;
Expand All @@ -174,13 +174,13 @@ contract FactchainCommunity is Ownable, IFactchainCommunity {
creator: _creator,
rater: rater,
reward: reward,
stake: MINIMUM_STAKE_PER_RATING
stake: minimumStakePerRating
});
} else if (delta > 2) {
uint96 slash = delta - 2;
// This will revert if contract current balance
// (address(this).balance) < MINIMUM_STAKE_PER_RATING - slash
(bool result,) = payable(rater).call{value: MINIMUM_STAKE_PER_RATING - slash}("");
// (address(this).balance) < minimumStakePerRating - slash
(bool result,) = payable(rater).call{value: minimumStakePerRating - slash}("");
if (!result) revert FailedToSlash();

userStats[rater].ethSlashed += slash;
Expand All @@ -189,7 +189,7 @@ contract FactchainCommunity is Ownable, IFactchainCommunity {
creator: _creator,
rater: rater,
slash: slash,
stake: MINIMUM_STAKE_PER_RATING
stake: minimumStakePerRating
});
}
}
Expand All @@ -201,7 +201,7 @@ contract FactchainCommunity is Ownable, IFactchainCommunity {

/// @notice Create a new note
function createNote(string memory _postUrl, string memory _content) external payable {
if (msg.value != MINIMUM_STAKE_PER_NOTE) revert InsufficientStake();
if (msg.value != minimumStakePerNote) revert InsufficientStake();
if (!isPostUrlValid(bytes(_postUrl))) revert PostUrlInvalid();
if (!isContentValid(bytes(_content))) revert ContentInvalid();
if (noteExists(_postUrl, msg.sender)) revert NoteAlreadyExists();
Expand All @@ -210,12 +210,12 @@ contract FactchainCommunity is Ownable, IFactchainCommunity {
Note({postUrl: _postUrl, content: _content, creator: msg.sender, finalRating: 0});

userStats[msg.sender].numberNotes += 1;
emit NoteCreated({postUrl: _postUrl, creator: msg.sender, stake: MINIMUM_STAKE_PER_NOTE});
emit NoteCreated({postUrl: _postUrl, creator: msg.sender, stake: minimumStakePerNote});
}

/// @notice Rate an existing note
function rateNote(string memory _postUrl, address _creator, uint8 _rating) external payable {
if (msg.value != MINIMUM_STAKE_PER_RATING) revert InsufficientStake();
if (msg.value != minimumStakePerRating) revert InsufficientStake();
if (!isRatingValid(_rating)) revert RatingInvalid();
if (_creator == msg.sender) revert CantRateOwnNote();
if (!noteExists(_postUrl, _creator)) revert NoteDoesNotExist();
Expand All @@ -231,7 +231,7 @@ contract FactchainCommunity is Ownable, IFactchainCommunity {
creator: _creator,
rater: msg.sender,
rating: _rating,
stake: MINIMUM_STAKE_PER_RATING
stake: minimumStakePerRating
});
}

Expand All @@ -255,4 +255,14 @@ contract FactchainCommunity is Ownable, IFactchainCommunity {
rewardOrSlashRaters(_postUrl, _creator);
emit NoteFinalised({postUrl: _postUrl, creator: _creator, finalRating: _finalRating});
}

/// @notice Set minimum staking for note creation
function setMinimumStakePerNote(uint64 _miniumStakePerNote) external onlyOwner {
minimumStakePerNote = _miniumStakePerNote;
}

/// @notice Set minimum staking for note rating
function setMinimumStakePerRating(uint64 _minimumStakePerRating) external onlyOwner {
minimumStakePerRating = _minimumStakePerRating;
}
}
16 changes: 10 additions & 6 deletions fc-community-contracts/src/FactchainSFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ interface IFactchainSFT is IFactchainSFTEvents {
contract FactchainSFT is Ownable, ERC1155URIStorage, IFactchainSFT {
address public FACTCHAIN_NFT_CONTRACT;
uint256 public constant FACTCHAINERS_MINT_SUPPLY = 42;
uint256 public constant MINT_PRICE = 1_000_000;
uint256 public mintPrice = 1_000_000_000_000_000;

mapping(uint256 => uint256) private _supply;
mapping(uint256 => uint256) public supply;

/// @notice Mapping of creators's addresses to NFT
mapping(uint256 => address) private _creatorsNFT;
Expand All @@ -44,11 +44,15 @@ contract FactchainSFT is Ownable, ERC1155URIStorage, IFactchainSFT {
emit FactchainNFTContractUpdated(_factchainNFTContract);
}

function setMintPrice(uint256 _mintPrice) public onlyOwner {
mintPrice = _mintPrice;
}

function initialMint(address creator, address[] memory raters, string memory ipfsHash, uint256 id) public returns (uint256) {
if (msg.sender != FACTCHAIN_NFT_CONTRACT) {
revert ReservedToFactchain();
}
_supply[id] = FACTCHAINERS_MINT_SUPPLY;
supply[id] = FACTCHAINERS_MINT_SUPPLY;
_creatorsNFT[id] = creator;
_setURI(id, ipfsHash);
for (uint256 i = 0; i < raters.length; ++i) {
Expand All @@ -58,12 +62,12 @@ contract FactchainSFT is Ownable, ERC1155URIStorage, IFactchainSFT {
}

function mint(uint256 id, uint256 value) external payable {
if (msg.value != MINT_PRICE * value) revert BadMintPrice();
if (msg.value != mintPrice * value) revert BadMintPrice();
if (value <= 0) revert ValueError();
if (value > _supply[id]) {
if (value > supply[id]) {
revert SupplyExhausted();
}
_supply[id] -= value;
supply[id] -= value;
address creator = _creatorsNFT[id];
uint256 reward = msg.value / 2;
(bool result,) = payable(creator).call{value: reward}("");
Expand Down
10 changes: 7 additions & 3 deletions fc-community-contracts/src/XCommunityNotes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ interface IXCommunityNotes is IXCommunityNotesEvents {
/// @dev
contract XCommunityNotes is Ownable, ERC1155, IXCommunityNotes {
uint256 public constant MAX_TOKEN_SUPPLY = 42;
uint256 public constant MINT_PRICE = 1_000_000;
uint256 public constant SUPPLY_EXHAUSTED = MAX_TOKEN_SUPPLY + 1;
uint256 public mintPrice = 1_000_000_000_000_000;

address public backend;
mapping(uint256 id => uint256) public supply;
Expand All @@ -58,6 +58,10 @@ contract XCommunityNotes is Ownable, ERC1155, IXCommunityNotes {
emit NewBackend(backend);
}

function setMintPrice(uint256 _mintPrice) public onlyOwner {
mintPrice = _mintPrice;
}

function getTokenID(string memory url) public view returns (uint256) {
// the token ID is a 9 to 10 digits number calculated from
// the url hash by converting to decimal its first 8 hex characters.
Expand All @@ -71,14 +75,14 @@ contract XCommunityNotes is Ownable, ERC1155, IXCommunityNotes {

function mint(uint256 id, uint256 value) public payable {
if (value <= 0) revert ValueError();
if (msg.value != MINT_PRICE * value) revert BadMintPrice();
if (msg.value != mintPrice * value) revert BadMintPrice();
if (supply[id] == SUPPLY_EXHAUSTED) revert SupplyExhausted();
if (supply[id] == 0) revert UnknownToken();
if (value > supply[id]) {
uint256 supplyCache = supply[id];
supply[id] = SUPPLY_EXHAUSTED;
_mint(msg.sender, id, supplyCache, "");
uint256 amount = (value - supplyCache) * MINT_PRICE;
uint256 amount = (value - supplyCache) * mintPrice;
// use call rather than transfer
// to support Smart Contract Wallets.
(bool result,) = payable(msg.sender).call{value: amount}("");
Expand Down
Loading

0 comments on commit 64a1739

Please sign in to comment.