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

Token symbol uniqueness #57

Merged
merged 12 commits into from
Apr 10, 2023
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
{
"files": "*.sol",
"options": {
"parser": "solidity-parse",
"printWidth": 180,
"tabWidth": 4,
"useTabs": false,
Expand Down
39 changes: 39 additions & 0 deletions docs/facets/IAdminFacet.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,42 @@ Check if object can be tokenized
| --- | --- | --- |
|`_objectId` | bytes32 | ID of the object|
<br></br>
### lockFunction
System Admin can lock a function
This toggles FunctionLockedStorage.lock to true
```solidity
function lockFunction(
bytes4 functionSelector
) external
```
#### Arguments:
| Argument | Type | Description |
| --- | --- | --- |
|`functionSelector` | bytes4 | the bytes4 function selector|
<br></br>
### unlockFunction
System Admin can unlock a function
This toggles FunctionLockedStorage.lock to false
```solidity
function unlockFunction(
bytes4 functionSelector
) external
```
#### Arguments:
| Argument | Type | Description |
| --- | --- | --- |
|`functionSelector` | bytes4 | the bytes4 function selector|
<br></br>
### isFunctionLocked
Check if a function has been locked by a system admin
This views FunctionLockedStorage.lock
```solidity
function isFunctionLocked(
bytes4 functionSelector
) external returns (bool)
```
#### Arguments:
| Argument | Type | Description |
| --- | --- | --- |
|`functionSelector` | bytes4 | the bytes4 function selector|
<br></br>
16 changes: 16 additions & 0 deletions docs/facets/IEntityFacet.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,22 @@ Enable an entity to be tokenized
|`_symbol` | string | The symbol assigned to the entity token
|`_name` | string | The name assigned to the entity token|
<br></br>
### updateEntityTokenInfo
Update entity token name and symbol
```solidity
function updateEntityTokenInfo(
bytes32 _entityId,
string _symbol,
string _name
) external
```
#### Arguments:
| Argument | Type | Description |
| --- | --- | --- |
|`_entityId` | bytes32 | ID of the entity
|`_symbol` | string | New entity token symbol
|`_name` | string | New entity token name|
<br></br>
### startTokenSale
Start token sale of `_amount` tokens for total price of `_totalPrice`
Entity tokens are minted when the sale is started
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"glob": "^8.0.3",
"prettier": "^2.7.1",
"prettier-plugin-solidity": "^1.0.0-beta.19",
"solc": "^0.8.16",
"solc": "0.8.17",
"solhint": "^3.3.7",
"solidity-coverage": "^0.7.21",
"solidity-docgen": "^0.5.17"
Expand Down
2 changes: 2 additions & 0 deletions src/diamonds/nayms/AppStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity 0.8.17;

/// @notice storage for nayms v3 decentralized insurance platform

// solhint-disable no-global-import
import "./interfaces/FreeStructs.sol";

struct AppStorage {
Expand Down Expand Up @@ -74,6 +75,7 @@ struct AppStorage {
mapping(bytes32 => uint256) upgradeScheduled; // id of the upgrade => the time that the upgrade is valid until.
uint256 upgradeExpiration; // the period of time that an upgrade is valid until.
uint256 sysAdmins; // counter for the number of sys admin accounts currently assigned
mapping(string => bytes32) tokenSymbolObjectId; // reverse mapping token symbol => object ID, to ensure symbol uniqueness
}

struct FunctionLockedStorage {
Expand Down
14 changes: 14 additions & 0 deletions src/diamonds/nayms/facets/EntityFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,20 @@ contract EntityFacet is IEntityFacet, Modifiers, ReentrancyGuard {
LibObject._enableObjectTokenization(_objectId, _symbol, _name);
}

/**
* @notice Update entity token name and symbol
* @param _entityId ID of the entity
* @param _symbol New entity token symbol
* @param _name New entity token name
*/
function updateEntityTokenInfo(
bytes32 _entityId,
string memory _symbol,
string memory _name
) external assertSysAdmin {
LibObject._updateTokenInfo(_entityId, _symbol, _name);
}

/**
* @notice Start token sale of `_amount` tokens for total price of `_totalPrice`
* @dev Entity tokens are minted when the sale is started
Expand Down
12 changes: 12 additions & 0 deletions src/diamonds/nayms/interfaces/IEntityFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ interface IEntityFacet {
string memory _name
) external;

/**
* @notice Update entity token name and symbol
* @param _entityId ID of the entity
* @param _symbol New entity token symbol
* @param _name New entity token name
*/
function updateEntityTokenInfo(
bytes32 _entityId,
string memory _symbol,
string memory _name
) external;

/**
* @notice Start token sale of `_amount` tokens for total price of `_totalPrice`
* @dev Entity tokens are minted when the sale is started
Expand Down
19 changes: 12 additions & 7 deletions src/diamonds/nayms/libs/LibAdmin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,18 @@ library LibAdmin {
}
AppStorage storage s = LibAppStorage.diamondStorage();

bool alreadyAdded = s.externalTokenSupported[_tokenAddress];
if (!alreadyAdded) {
s.externalTokenSupported[_tokenAddress] = true;
LibObject._createObject(LibHelpers._getIdForAddress(_tokenAddress));
s.supportedExternalTokens.push(_tokenAddress);
emit SupportedTokenAdded(_tokenAddress);
}
require(!s.externalTokenSupported[_tokenAddress], "external token already added");

string memory symbol = LibERC20.symbol(_tokenAddress);
require(LibObject._tokenSymbolNotUsed(symbol), "token symbol already in use");

s.externalTokenSupported[_tokenAddress] = true;
bytes32 tokenId = LibHelpers._getIdForAddress(_tokenAddress);
LibObject._createObject(tokenId);
s.supportedExternalTokens.push(_tokenAddress);
s.tokenSymbolObjectId[symbol] = tokenId;

emit SupportedTokenAdded(_tokenAddress);
}

function _getSupportedExternalTokens() internal view returns (address[] memory) {
Expand Down
8 changes: 4 additions & 4 deletions src/diamonds/nayms/libs/LibFeeRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ library LibFeeRouter {
// Pay Nayms, LTD commission
LibTokenizedVault._internalTransfer(_takerId, LibHelpers._stringToBytes32(LibConstants.NAYMS_LTD_IDENTIFIER), _tokenId, tc.commissionNaymsLtd);

// Pay Nayms Discretionsry Fund commission
// Pay Nayms Discretionary Fund commission
LibTokenizedVault._internalTransfer(_takerId, LibHelpers._stringToBytes32(LibConstants.NDF_IDENTIFIER), _tokenId, tc.commissionNDF);

// Pay Staking Mechanism commission
Expand All @@ -66,7 +66,7 @@ library LibFeeRouter {
// Pay market maker commission
LibTokenizedVault._internalTransfer(_takerId, _makerId, _tokenId, tc.commissionMaker);

// Work it out again so the math is precise, ignoring remainers
// Work it out again so the math is precise, ignoring remainders
commissionPaid_ = tc.totalCommissions;

emit TradingCommissionsPaid(_takerId, _tokenId, commissionPaid_);
Expand Down Expand Up @@ -107,7 +107,7 @@ library LibFeeRouter {
// Pay Nayms, LTD commission
tc.commissionNaymsLtd = (s.tradingCommissionNaymsLtdBP * tc.roughCommissionPaid) / LibConstants.BP_FACTOR;

// Pay Nayms Discretionsry Fund commission
// Pay Nayms Discretionary Fund commission
tc.commissionNDF = (s.tradingCommissionNDFBP * tc.roughCommissionPaid) / LibConstants.BP_FACTOR;

// Pay Staking Mechanism commission
Expand All @@ -116,7 +116,7 @@ library LibFeeRouter {
// Pay market maker commission
tc.commissionMaker = (s.tradingCommissionMakerBP * tc.roughCommissionPaid) / LibConstants.BP_FACTOR;

// Work it out again so the math is precise, ignoring remainers
// Work it out again so the math is precise, ignoring remainders
tc.totalCommissions = tc.commissionNaymsLtd + tc.commissionNDF + tc.commissionSTM + tc.commissionMaker;
}

Expand Down
29 changes: 28 additions & 1 deletion src/diamonds/nayms/libs/LibObject.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ERC20Wrapper } from "../../../erc20/ERC20Wrapper.sol";
/// @notice Contains internal methods for core Nayms system functionality
library LibObject {
event TokenWrapped(bytes32 indexed entityId, address tokenWrapper);
event TokenInfoUpdated(bytes32 indexed objectId, string symbol, string name);

function _createObject(
bytes32 _objectId,
Expand Down Expand Up @@ -77,6 +78,11 @@ library LibObject {
return (bytes(s.objectTokenSymbol[_objectId]).length != 0);
}

function _tokenSymbolNotUsed(string memory _symbol) internal view returns (bool) {
AppStorage storage s = LibAppStorage.diamondStorage();
return s.tokenSymbolObjectId[_symbol] == bytes32(0);
}

function _enableObjectTokenization(
bytes32 _objectId,
string memory _symbol,
Expand All @@ -86,17 +92,38 @@ library LibObject {
if (bytes(_symbol).length == 0) {
revert MissingSymbolWhenEnablingTokenization(_objectId);
}
require(bytes(_symbol).length < 16, "symbol must be less than 16 characters");

// Ensure the entity exists before tokenizing the entity, otherwise revert.
if (!s.existingEntities[_objectId]) {
revert EntityDoesNotExist(_objectId);
}

require(!_isObjectTokenizable(_objectId), "object already tokenized");
require(bytes(_symbol).length < 16, "symbol must be less than 16 characters");
require(_tokenSymbolNotUsed(_symbol), "token symbol already in use");

s.objectTokenSymbol[_objectId] = _symbol;
s.objectTokenName[_objectId] = _name;
s.tokenSymbolObjectId[_symbol] = _objectId;
}

function _updateTokenInfo(
bytes32 _objectId,
string memory _symbol,
string memory _name
) internal {
AppStorage storage s = LibAppStorage.diamondStorage();
require(_tokenSymbolNotUsed(_symbol), "token symbol already in use");
require(_isObjectTokenizable(_objectId), "object not tokenized");

string memory oldSymbol = s.objectTokenSymbol[_objectId];
delete s.tokenSymbolObjectId[oldSymbol];

s.objectTokenSymbol[_objectId] = _symbol;
s.objectTokenName[_objectId] = _name;
s.tokenSymbolObjectId[_symbol] = _objectId;

emit TokenInfoUpdated(_objectId, _symbol, _name);
}

function _isObjectTokenWrapped(bytes32 _objectId) internal view returns (bool) {
Expand Down
22 changes: 11 additions & 11 deletions src/diamonds/nayms/libs/LibTokenizedVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ library LibTokenizedVault {
* @param tokenId ID of token
* @param newAmountOwned new amount owned
* @param functionName Function name
* @param msgSender msg.sende
* @param msgSender msg.sender
*/
event InternalTokenBalanceUpdate(bytes32 indexed ownerId, bytes32 tokenId, uint256 newAmountOwned, string functionName, address msgSender);

Expand All @@ -23,14 +23,14 @@ library LibTokenizedVault {
* @param tokenId ID of token
* @param newTokenSupply New token supply
* @param functionName Function name
* @param msgSender msg.sende
* @param msgSender msg.sender
*/
event InternalTokenSupplyUpdate(bytes32 indexed tokenId, uint256 newTokenSupply, string functionName, address msgSender);

/**
* @dev Emitted when a dividend gets payed out.
* @param guid divident distribution ID
* @param from distribution intiator
* @param guid dividend distribution ID
* @param from distribution initiator
* @param to distribution receiver
* @param amount distributed amount
*/
Expand Down Expand Up @@ -99,7 +99,7 @@ library LibTokenizedVault {
uint256 supply = _internalTokenSupply(_tokenId);

// This must be done BEFORE the supply increases!!!
// This will calcualte the hypothetical dividends that would correspond to this number of shares.
// This will calculate the hypothetical dividends that would correspond to this number of shares.
// It must be added to the withdrawn dividend for every denomination for the user who receives the minted tokens
bytes32[] memory dividendDenominations = s.dividendDenominations[_tokenId];

Expand Down Expand Up @@ -141,22 +141,22 @@ library LibTokenizedVault {
//
// When a dividend is payed, you divide by the total supply and add it to the totalDividendPerToken
// Dividends are held by the diamond contract at: LibHelpers._stringToBytes32(LibConstants.DIVIDEND_BANK_IDENTIFIER)
// When dividends are paid, they are transfered OUT of that same diamond contract ID.
// When dividends are paid, they are transferred OUT of that same diamond contract ID.
//
// To calculate withdrawableDividiend = ownedTokens * totalDividendPerToken - totalWithdrawnDividendPerOwner
// To calculate withdrawableDividend = ownedTokens * totalDividendPerToken - totalWithdrawnDividendPerOwner
//
// When a dividend is collected you set the totalWithdrawnDividendPerOwner to the total amount the owner withdrew
//
// When you trasnsfer, you pay out all dividends to previous owner first, then transfer ownership
// When you transfer, you pay out all dividends to previous owner first, then transfer ownership
// !!!YOU ALSO TRANSFER totalWithdrawnDividendPerOwner for those shares!!!
// totalWithdrawnDividendPerOwner(for new owner) += numberOfSharesTransfered * totalDividendPerToken
// totalWithdrawnDividendPerOwner(for previous owner) -= numberOfSharesTransfered * totalDividendPerToken (can be optimized)
// totalWithdrawnDividendPerOwner(for new owner) += numberOfSharesTransferred * totalDividendPerToken
// totalWithdrawnDividendPerOwner(for previous owner) -= numberOfSharesTransferred * totalDividendPerToken (can be optimized)
//
// When minting
// Add the token balance to the new owner
// totalWithdrawnDividendPerOwner(for new owner) += numberOfSharesMinted * totalDividendPerToken
//
// When doing the division theser will be dust. Leave the dust in the diamond!!!
// When doing the division these will be dust. Leave the dust in the diamond!!!
function _withdrawDividend(
bytes32 _ownerId,
bytes32 _tokenId,
Expand Down