Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
DSToken
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.8.13; import "./IDSToken.sol"; import "../utils/ProxyTarget.sol"; import "./StandardToken.sol"; //SPDX-License-Identifier: UNLICENSED contract DSToken is ProxyTarget, Initializable, StandardToken { // using FeaturesLibrary for SupportedFeatures; using TokenLibrary for TokenLibrary.SupportedFeatures; uint256 internal constant OMNIBUS_NO_ACTION = 0; function initialize(string memory _name, string memory _symbol, uint8 _decimals) public virtual initializer forceInitializeFromProxy { StandardToken.initialize(); VERSIONS.push(5); name = _name; symbol = _symbol; decimals = _decimals; } /****************************** TOKEN CONFIGURATION *******************************/ function setFeature(uint8 featureIndex, bool enable) public onlyMaster { supportedFeatures.setFeature(featureIndex, enable); } function setFeatures(uint256 features) public onlyMaster { supportedFeatures.value = features; } function setCap(uint256 _cap) public override onlyTransferAgentOrAbove { require(cap == 0, "Token cap already set"); require(_cap > 0); cap = _cap; } function totalIssued() public view returns (uint256) { return tokenData.totalIssued; } /****************************** TOKEN ISSUANCE (MINTING) *******************************/ /** * @dev Issues unlocked tokens * @param _to address The address which is going to receive the newly issued tokens * @param _value uint256 the value of tokens to issue * @return true if successful */ function issueTokens( address _to, uint256 _value /*onlyIssuerOrAbove*/ ) public override returns (bool) { issueTokensCustom(_to, _value, block.timestamp, 0, "", 0); return true; } /** * @dev Issuing tokens from the fund * @param _to address The address which is going to receive the newly issued tokens * @param _value uint256 the value of tokens to issue * @param _valueLocked uint256 value of tokens, from those issued, to lock immediately. * @param _reason reason for token locking * @param _releaseTime timestamp to release the lock (or 0 for locks which can only released by an unlockTokens call) * @return true if successful */ function issueTokensCustom(address _to, uint256 _value, uint256 _issuanceTime, uint256 _valueLocked, string memory _reason, uint64 _releaseTime) public virtual override returns ( /*onlyIssuerOrAbove*/ bool ) { uint256[] memory valuesLocked; uint64[] memory releaseTimes; if (_valueLocked > 0) { valuesLocked = new uint256[](1); releaseTimes = new uint64[](1); valuesLocked[0] = _valueLocked; releaseTimes[0] = _releaseTime; } issueTokensWithMultipleLocks(_to, _value, _issuanceTime, valuesLocked, _reason, releaseTimes); return true; } function issueTokensWithMultipleLocks(address _to, uint256 _value, uint256 _issuanceTime, uint256[] memory _valuesLocked, string memory _reason, uint64[] memory _releaseTimes) public virtual override onlyIssuerOrAbove returns (bool) { TokenLibrary.issueTokensCustom(tokenData, getCommonServices(), getLockManager(), _to, _value, _issuanceTime, _valuesLocked, _releaseTimes, _reason, cap); emit Transfer(address(0), _to, _value); checkWalletsForList(address(0), _to); return true; } function issueTokensWithNoCompliance(address _to, uint256 _value) public virtual override onlyIssuerOrAbove { require(getRegistryService().isWallet(_to), "Unknown wallet"); TokenLibrary.issueTokensWithNoCompliance(tokenData, getCommonServices(), _to, _value, block.timestamp, cap); emit Transfer(address(0), _to, _value); } //********************* // TOKEN BURNING //********************* function burn(address _who, uint256 _value, string memory _reason) public virtual override onlyIssuerOrTransferAgentOrAbove { TokenLibrary.burn(tokenData, getCommonServices(), _who, _value); emit Burn(_who, _value, _reason); emit Transfer(_who, address(0), _value); checkWalletsForList(_who, address(0)); } function omnibusBurn(address _omnibusWallet, address _who, uint256 _value, string memory _reason) public override onlyTransferAgentOrAbove { require(_value <= tokenData.walletsBalances[_omnibusWallet]); TokenLibrary.omnibusBurn(tokenData, getCommonServices(), _omnibusWallet, _who, _value); emit OmnibusBurn(_omnibusWallet, _who, _value, _reason, getAssetTrackingMode(_omnibusWallet)); emit Burn(_omnibusWallet, _value, _reason); emit Transfer(_omnibusWallet, address(0), _value); checkWalletsForList(_omnibusWallet, address(0)); } //********************* // TOKEN SEIZING //********************* function seize(address _from, address _to, uint256 _value, string memory _reason) public virtual override onlyTransferAgentOrAbove { TokenLibrary.seize(tokenData, getCommonServices(), _from, _to, _value); emit Seize(_from, _to, _value, _reason); emit Transfer(_from, _to, _value); checkWalletsForList(_from, _to); } function omnibusSeize(address _omnibusWallet, address _from, address _to, uint256 _value, string memory _reason) public override onlyTransferAgentOrAbove { TokenLibrary.omnibusSeize(tokenData, getCommonServices(), _omnibusWallet, _from, _to, _value); emit OmnibusSeize(_omnibusWallet, _from, _value, _reason, getAssetTrackingMode(_omnibusWallet)); emit Seize(_omnibusWallet, _to, _value, _reason); emit Transfer(_omnibusWallet, _to, _value); checkWalletsForList(_omnibusWallet, _to); } //********************* // TRANSFER RESTRICTIONS //********************* /** * @dev Checks whether it can transfer with the compliance manager, if not -throws. */ modifier canTransfer(address _sender, address _receiver, uint256 _value) { getComplianceService().validateTransfer(_sender, _receiver, _value, paused, super.balanceOf(_sender)); _; } /** * @dev override for transfer with modifiers: * whether the token is not paused (checked in super class) * and that the sender is allowed to transfer tokens * @param _to The address that will receive the tokens. * @param _value The amount of tokens to be transferred. */ function transfer(address _to, uint256 _value) public virtual override canTransfer(msg.sender, _to, _value) returns (bool) { return postTransferImpl(super.transfer(_to, _value), msg.sender, _to, _value); } /** * @dev override for transfer with modifiers: * whether the token is not paused (checked in super class) * and that the sender is allowed to transfer tokens * @param _from The address that will send the tokens. * @param _to The address that will receive the tokens. * @param _value The amount of tokens to be transferred. */ function transferFrom(address _from, address _to, uint256 _value) public virtual override canTransfer(_from, _to, _value) returns (bool) { return postTransferImpl(super.transferFrom(_from, _to, _value), _from, _to, _value); } function postTransferImpl(bool _superResult, address _from, address _to, uint256 _value) internal returns (bool) { if (_superResult) { updateInvestorsBalancesOnTransfer(_from, _to, _value); } checkWalletsForList(_from, _to); return _superResult; } //********************* // WALLET ENUMERATION //**** function getWalletAt(uint256 _index) public view override returns (address) { require(_index > 0 && _index <= walletsCount); return walletsList[_index]; } function walletCount() public view override returns (uint256) { return walletsCount; } function checkWalletsForList(address _from, address _to) private { if (super.balanceOf(_from) == 0) { removeWalletFromList(_from); } if (super.balanceOf(_to) > 0) { addWalletToList(_to); } } function addWalletToList(address _address) private { //Check if it's already there uint256 existingIndex = walletsToIndexes[_address]; if (existingIndex == 0) { //If not - add it uint256 index = walletsCount + 1; walletsList[index] = _address; walletsToIndexes[_address] = index; walletsCount = index; } } function removeWalletFromList(address _address) private { //Make sure it's there uint256 existingIndex = walletsToIndexes[_address]; if (existingIndex != 0) { uint256 lastIndex = walletsCount; if (lastIndex != existingIndex) { //Put the last wallet instead of it (this will work even with 1 wallet in the list) address lastWalletAddress = walletsList[lastIndex]; walletsList[existingIndex] = lastWalletAddress; walletsToIndexes[lastWalletAddress] = existingIndex; } delete walletsToIndexes[_address]; delete walletsList[lastIndex]; walletsCount = lastIndex - 1; } } //************************************** // MISCELLANEOUS FUNCTIONS //************************************** function balanceOfInvestor(string memory _id) public view override returns (uint256) { return tokenData.investorsBalances[_id]; } function getAssetTrackingMode(address _omnibusWallet) internal view returns (uint8) { return getRegistryService().getOmnibusWalletController(_omnibusWallet).getAssetTrackingMode(); } function updateOmnibusInvestorBalance(address _omnibusWallet, address _wallet, uint256 _value, CommonUtils.IncDec _increase) public override onlyOmnibusWalletController(_omnibusWallet, IDSOmnibusWalletController(msg.sender)) returns (bool) { return updateInvestorBalance(_wallet, _value, _increase); } function emitOmnibusTransferEvent(address _omnibusWallet, address _from, address _to, uint256 _value) public override onlyOmnibusWalletController(_omnibusWallet, IDSOmnibusWalletController(msg.sender)) { emit OmnibusTransfer(_omnibusWallet, _from, _to, _value, getAssetTrackingMode(_omnibusWallet)); } function emitOmnibusTBEEvent(address omnibusWallet, int256 totalDelta, int256 accreditedDelta, int256 usAccreditedDelta, int256 usTotalDelta, int256 jpTotalDelta) public override onlyTBEOmnibus { emit OmnibusTBEOperation(omnibusWallet, totalDelta, accreditedDelta, usAccreditedDelta, usTotalDelta, jpTotalDelta); } function emitOmnibusTBETransferEvent(address omnibusWallet, string memory externalId) public override onlyTBEOmnibus { emit OmnibusTBETransfer(omnibusWallet, externalId); } function updateInvestorsBalancesOnTransfer(address _from, address _to, uint256 _value) internal { uint256 omnibusEvent = TokenLibrary.applyOmnibusBalanceUpdatesOnTransfer(tokenData, getRegistryService(), _from, _to, _value); if (omnibusEvent == OMNIBUS_NO_ACTION) { updateInvestorBalance(_from, _value, CommonUtils.IncDec.Decrease); updateInvestorBalance(_to, _value, CommonUtils.IncDec.Increase); } } function updateInvestorBalance(address _wallet, uint256 _value, CommonUtils.IncDec _increase) internal override returns (bool) { string memory investor = getRegistryService().getInvestor(_wallet); if (!CommonUtils.isEmptyString(investor)) { uint256 balance = balanceOfInvestor(investor); if (_increase == CommonUtils.IncDec.Increase) { balance += _value; } else { balance -= _value; } tokenData.investorsBalances[investor] = balance; } return true; } function preTransferCheck(address _from, address _to, uint256 _value) public view override returns (uint256 code, string memory reason) { return getComplianceService().preTransferCheck(_from, _to, _value); } function getCommonServices() internal view returns (address[] memory) { address[] memory services = new address[](3); services[0] = getDSService(COMPLIANCE_SERVICE); services[1] = getDSService(REGISTRY_SERVICE); services[2] = getDSService(OMNIBUS_TBE_CONTROLLER); return services; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`. // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`. // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a // good first aproximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1; uint256 x = a; if (x >> 128 > 0) { x >>= 128; result <<= 64; } if (x >> 64 > 0) { x >>= 64; result <<= 32; } if (x >> 32 > 0) { x >>= 32; result <<= 16; } if (x >> 16 > 0) { x >>= 16; result <<= 8; } if (x >> 8 > 0) { x >>= 8; result <<= 4; } if (x >> 4 > 0) { x >>= 4; result <<= 2; } if (x >> 2 > 0) { result <<= 1; } // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { uint256 result = sqrt(a); if (rounding == Rounding.Up && result * result < a) { result += 1; } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
pragma solidity ^0.8.13; import "./IDSComplianceConfigurationService.sol"; import "../data-stores/ComplianceConfigurationDataStore.sol"; import "../service/ServiceConsumer.sol"; import "../utils/ProxyTarget.sol"; //SPDX-License-Identifier: UNLICENSED contract ComplianceConfigurationService is ProxyTarget, IDSComplianceConfigurationService, ServiceConsumer, ComplianceConfigurationDataStore { function initialize() public override(IDSComplianceConfigurationService, ServiceConsumer) initializer forceInitializeFromProxy { IDSComplianceConfigurationService.initialize(); ServiceConsumer.initialize(); VERSIONS.push(8); } function setCountriesCompliance(string[] memory _countries, uint256[] memory _values) public override onlyTransferAgentOrAbove { require(_countries.length <= 35, "Exceeded the maximum number of countries"); require(_countries.length == _values.length, "Wrong length of parameters"); for (uint i = 0; i < _countries.length; i++) { setCountryCompliance(_countries[i], _values[i]); } } function setCountryCompliance(string memory _country, uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceStringToUIntMapRuleSet("countryCompliance", _country, countriesCompliances[_country], _value); countriesCompliances[_country] = _value; } function getCountryCompliance(string memory _country) public view override returns (uint256) { return countriesCompliances[_country]; } function getTotalInvestorsLimit() public view override returns (uint256) { return totalInvestorsLimit; } function setTotalInvestorsLimit(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("totalInvestorsLimit", totalInvestorsLimit, _value); totalInvestorsLimit = _value; } function getMinUSTokens() public view override returns (uint256) { return minUSTokens; } function setMinUSTokens(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("minUSTokens", minUSTokens, _value); minUSTokens = _value; } function getMinEUTokens() public view override returns (uint256) { return minEUTokens; } function setMinEUTokens(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("minEUTokens", minEUTokens, _value); minEUTokens = _value; } function getUSInvestorsLimit() public view override returns (uint256) { return usInvestorsLimit; } function setUSInvestorsLimit(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("usInvestorsLimit", usInvestorsLimit, _value); usInvestorsLimit = _value; } function getJPInvestorsLimit() public view override returns (uint256) { return jpInvestorsLimit; } function setJPInvestorsLimit(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("jpInvestorsLimit", jpInvestorsLimit, _value); jpInvestorsLimit = _value; } function getUSAccreditedInvestorsLimit() public view override returns (uint256) { return usAccreditedInvestorsLimit; } function setUSAccreditedInvestorsLimit(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("usAccreditedInvestorsLimit", usAccreditedInvestorsLimit, _value); usAccreditedInvestorsLimit = _value; } function getNonAccreditedInvestorsLimit() public view override returns (uint256) { return nonAccreditedInvestorsLimit; } function setNonAccreditedInvestorsLimit(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("nonAccreditedInvestorsLimit", nonAccreditedInvestorsLimit, _value); nonAccreditedInvestorsLimit = _value; } function getMaxUSInvestorsPercentage() public view override returns (uint256) { return maxUSInvestorsPercentage; } function setMaxUSInvestorsPercentage(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("maxUSInvestorsPercentage", maxUSInvestorsPercentage, _value); maxUSInvestorsPercentage = _value; } function getBlockFlowbackEndTime() public view override returns (uint256) { return blockFlowbackEndTime; } function setBlockFlowbackEndTime(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("blockFlowbackEndTime", blockFlowbackEndTime, _value); blockFlowbackEndTime = _value; } function getNonUSLockPeriod() public view override returns (uint256) { return nonUSLockPeriod; } function setNonUSLockPeriod(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("nonUSLockPeriod", nonUSLockPeriod, _value); nonUSLockPeriod = _value; } function getMinimumTotalInvestors() public view override returns (uint256) { return minimumTotalInvestors; } function setMinimumTotalInvestors(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("minimumTotalInvestors", minimumTotalInvestors, _value); minimumTotalInvestors = _value; } function getMinimumHoldingsPerInvestor() public view override returns (uint256) { return minimumHoldingsPerInvestor; } function setMinimumHoldingsPerInvestor(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("minimumHoldingsPerInvestor", minimumHoldingsPerInvestor, _value); minimumHoldingsPerInvestor = _value; } function getMaximumHoldingsPerInvestor() public view override returns (uint256) { return maximumHoldingsPerInvestor; } function setMaximumHoldingsPerInvestor(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("maximumHoldingsPerInvestor", maximumHoldingsPerInvestor, _value); maximumHoldingsPerInvestor = _value; } function getEURetailInvestorsLimit() public view override returns (uint256) { return euRetailInvestorsLimit; } function setEURetailInvestorsLimit(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("euRetailInvestorsLimit", euRetailInvestorsLimit, _value); euRetailInvestorsLimit = _value; } function getUSLockPeriod() public view override returns (uint256) { return usLockPeriod; } function setUSLockPeriod(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("usLockPeriod", usLockPeriod, _value); usLockPeriod = _value; } function getForceFullTransfer() public view override returns (bool) { return forceFullTransfer; } function setForceFullTransfer(bool _value) public override onlyTransferAgentOrAbove { emit DSComplianceBoolRuleSet("forceFullTransfer", forceFullTransfer, _value); forceFullTransfer = _value; } function getForceAccreditedUS() public view override returns (bool) { return forceAccreditedUS; } function setForceAccreditedUS(bool _value) public override onlyTransferAgentOrAbove { emit DSComplianceBoolRuleSet("forceAccreditedUS", forceAccreditedUS, _value); forceAccreditedUS = _value; } function getForceAccredited() public view override returns (bool) { return forceAccredited; } function setForceAccredited(bool _value) public override onlyTransferAgentOrAbove { emit DSComplianceBoolRuleSet("forceAccredited", forceAccredited, _value); forceAccredited = _value; } function getWorldWideForceFullTransfer() public view override returns (bool) { return worldWideForceFullTransfer; } function setWorldWideForceFullTransfer(bool _value) public override onlyTransferAgentOrAbove { emit DSComplianceBoolRuleSet("worldWideForceFullTransfer", worldWideForceFullTransfer, _value); worldWideForceFullTransfer = _value; } function getAuthorizedSecurities() public view override returns (uint256) { return authorizedSecurities; } function setAuthorizedSecurities(uint256 _value) public override onlyTransferAgentOrAbove { emit DSComplianceUIntRuleSet("authorizedSecurities", authorizedSecurities, _value); authorizedSecurities = _value; } function getDisallowBackDating() public view override returns (bool) { return disallowBackDating; } function setDisallowBackDating(bool _value) public override onlyTransferAgentOrAbove { emit DSComplianceBoolRuleSet("disallowBackDating", disallowBackDating, _value); disallowBackDating = _value; } function setAll(uint256[] memory _uint_values, bool[] memory _bool_values) public override onlyTransferAgentOrAbove { require(_uint_values.length == 16, "Wrong length of parameters"); require(_bool_values.length == 5, "Wrong length of parameters"); setTotalInvestorsLimit(_uint_values[0]); setMinUSTokens(_uint_values[1]); setMinEUTokens(_uint_values[2]); setUSInvestorsLimit(_uint_values[3]); setUSAccreditedInvestorsLimit(_uint_values[4]); setNonAccreditedInvestorsLimit(_uint_values[5]); setMaxUSInvestorsPercentage(_uint_values[6]); setBlockFlowbackEndTime(_uint_values[7]); setNonUSLockPeriod(_uint_values[8]); setMinimumTotalInvestors(_uint_values[9]); setMinimumHoldingsPerInvestor(_uint_values[10]); setMaximumHoldingsPerInvestor(_uint_values[11]); setEURetailInvestorsLimit(_uint_values[12]); setUSLockPeriod(_uint_values[13]); setJPInvestorsLimit(_uint_values[14]); setAuthorizedSecurities(_uint_values[15]); setForceFullTransfer(_bool_values[0]); setForceAccredited(_bool_values[1]); setForceAccreditedUS(_bool_values[2]); setWorldWideForceFullTransfer(_bool_values[3]); setDisallowBackDating(_bool_values[4]); } function getAll() public view override returns (uint256[] memory, bool[] memory) { uint256[] memory uintValues = new uint256[](16); bool[] memory boolValues = new bool[](5); uintValues[0] = getTotalInvestorsLimit(); uintValues[1] = getMinUSTokens(); uintValues[2] = getMinEUTokens(); uintValues[3] = getUSInvestorsLimit(); uintValues[4] = getUSAccreditedInvestorsLimit(); uintValues[5] = getNonAccreditedInvestorsLimit(); uintValues[6] = getMaxUSInvestorsPercentage(); uintValues[7] = getBlockFlowbackEndTime(); uintValues[8] = getNonUSLockPeriod(); uintValues[9] = getMinimumTotalInvestors(); uintValues[10] = getMinimumHoldingsPerInvestor(); uintValues[11] = getMaximumHoldingsPerInvestor(); uintValues[12] = getEURetailInvestorsLimit(); uintValues[13] = getUSLockPeriod(); uintValues[14] = getJPInvestorsLimit(); uintValues[15] = getAuthorizedSecurities(); boolValues[0] = getForceFullTransfer(); boolValues[1] = getForceAccredited(); boolValues[2] = getForceAccreditedUS(); boolValues[3] = getWorldWideForceFullTransfer(); boolValues[4] = getDisallowBackDating(); return (uintValues, boolValues); } }
pragma solidity ^0.8.13; import "../utils/ProxyTarget.sol"; import "./IDSComplianceService.sol"; import "../service/ServiceConsumer.sol"; import "../data-stores/ComplianceServiceDataStore.sol"; /** * @title Compliance service main implementation. * * Combines the different implementation files for the compliance service and serves as a base class for * concrete implementation. * * To create a concrete implementation of a compliance service, one should inherit from this contract, * and implement the five functions - recordIssuance,checkTransfer,recordTransfer,recordBurn and recordSeize. * The rest of the functions should only be overridden in rare circumstances. */ //SPDX-License-Identifier: UNLICENSED abstract contract ComplianceService is ProxyTarget, Initializable, IDSComplianceService, ServiceConsumer, ComplianceServiceDataStore { function initialize() public virtual override(IDSComplianceService, ServiceConsumer) forceInitializeFromProxy { IDSComplianceService.initialize(); ServiceConsumer.initialize(); VERSIONS.push(7); } function validateTransfer( address _from, address _to, uint256 _value ) public override onlyToken returns (bool) { uint256 code; string memory reason; (code, reason) = preTransferCheck(_from, _to, _value); require(code == 0, reason); return recordTransfer(_from, _to, _value); } function validateTransfer( address _from, address _to, uint256 _value, bool _paused, uint256 _balanceFrom ) public virtual override onlyToken returns (bool) { uint256 code; string memory reason; (code, reason) = newPreTransferCheck(_from, _to, _value, _balanceFrom, _paused); require(code == 0, reason); return recordTransfer(_from, _to, _value); } function validateIssuance( address _to, uint256 _value, uint256 _issuanceTime ) public override onlyToken returns (bool) { uint256 code; string memory reason; uint256 authorizedSecurities = getComplianceConfigurationService().getAuthorizedSecurities(); require(authorizedSecurities == 0 || getToken().totalSupply() + _value <= authorizedSecurities, MAX_AUTHORIZED_SECURITIES_EXCEEDED); (code, reason) = preIssuanceCheck(_to, _value); require(code == 0, reason); uint256 issuanceTime = validateIssuanceTime(_issuanceTime); return recordIssuance(_to, _value, issuanceTime); } function validateIssuanceWithNoCompliance( address _to, uint256 _value, uint256 _issuanceTime ) public override onlyToken returns (bool) { uint256 authorizedSecurities = getComplianceConfigurationService().getAuthorizedSecurities(); require(authorizedSecurities == 0 || getToken().totalSupply() + _value <= authorizedSecurities, MAX_AUTHORIZED_SECURITIES_EXCEEDED); uint256 issuanceTime = validateIssuanceTime(_issuanceTime); return recordIssuance(_to, _value, issuanceTime); } function validateBurn(address _who, uint256 _value) public virtual override onlyToken returns (bool) { return recordBurn(_who, _value); } function validateSeize( address _from, address _to, uint256 _value ) public virtual override onlyToken returns (bool) { require(getWalletManager().isIssuerSpecialWallet(_to), "Target wallet type error"); return recordSeize(_from, _to, _value); } /** * @dev Verify disallowBackDating compliance: if set to false returns _issuanceTime parameter, otherwise returns current timestamp * @param _issuanceTime. * @return issuanceTime */ function validateIssuanceTime(uint256 _issuanceTime) public view override returns (uint256 issuanceTime) { if (!getComplianceConfigurationService().getDisallowBackDating()) { return _issuanceTime; } return block.timestamp; } function newPreTransferCheck( address _from, address _to, uint256 _value, uint256 _balanceFrom, bool _pausedToken ) public view virtual returns (uint256 code, string memory reason) { if (_pausedToken) { return (10, TOKEN_PAUSED); } if (_balanceFrom < _value) { return (15, NOT_ENOUGH_TOKENS); } if (getLockManager().getTransferableTokens(_from, block.timestamp) < _value) { return (16, TOKENS_LOCKED); } return checkTransfer(_from, _to, _value); } function preTransferCheck( address _from, address _to, uint256 _value ) public view virtual override returns (uint256 code, string memory reason) { if (getToken().isPaused()) { return (10, TOKEN_PAUSED); } if (getToken().balanceOf(_from) < _value) { return (15, NOT_ENOUGH_TOKENS); } if (getLockManager().getTransferableTokens(_from, block.timestamp) < _value) { return (16, TOKENS_LOCKED); } return checkTransfer(_from, _to, _value); } function preInternalTransferCheck( address _from, address _to, uint256 _value ) public view virtual override returns (uint256 code, string memory reason) { if (getToken().isPaused()) { return (10, TOKEN_PAUSED); } return checkTransfer(_from, _to, _value); } function preIssuanceCheck( address, /*_to*/ uint256 /*_value*/ ) public view virtual override returns (uint256 code, string memory reason) { return (0, VALID); } function adjustInvestorCountsAfterCountryChange( string memory, /*_id*/ string memory, /*_country*/ string memory /*_prevCountry*/ ) public virtual override returns (bool) { return true; } // These functions should be implemented by the concrete compliance manager function recordIssuance( address _to, uint256 _value, uint256 _issuanceTime ) internal virtual returns (bool); function recordTransfer( address _from, address _to, uint256 _value ) internal virtual returns (bool); function recordBurn(address _who, uint256 _value) internal virtual returns (bool); function recordSeize( address _from, address _to, uint256 _value ) internal virtual returns (bool); function checkTransfer( address _from, address _to, uint256 _value ) internal view virtual returns (uint256, string memory); }
pragma solidity ^0.8.13; import "./ComplianceServiceWhitelisted.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; library ComplianceServiceLibrary { uint256 internal constant DS_TOKEN = 0; uint256 internal constant REGISTRY_SERVICE = 1; uint256 internal constant WALLET_MANAGER = 2; uint256 internal constant COMPLIANCE_CONFIGURATION_SERVICE = 3; uint256 internal constant LOCK_MANAGER = 4; uint256 internal constant COMPLIANCE_SERVICE = 5; uint256 internal constant OMNIBUS_TBE_CONTROLLER = 6; uint256 internal constant NONE = 0; uint256 internal constant US = 1; uint256 internal constant EU = 2; uint256 internal constant FORBIDDEN = 4; uint256 internal constant JP = 8; string internal constant TOKEN_PAUSED = "Token paused"; string internal constant NOT_ENOUGH_TOKENS = "Not enough tokens"; string internal constant VALID = "Valid"; string internal constant TOKENS_LOCKED = "Tokens locked"; string internal constant ONLY_FULL_TRANSFER = "Only full transfer"; string internal constant FLOWBACK = "Flowback"; string internal constant WALLET_NOT_IN_REGISTRY_SERVICE = "Wallet not in registry service"; string internal constant AMOUNT_OF_TOKENS_UNDER_MIN = "Amount of tokens under min"; string internal constant AMOUNT_OF_TOKENS_ABOVE_MAX = "Amount of tokens above max"; string internal constant HOLD_UP = "Under lock-up"; string internal constant DESTINATION_RESTRICTED = "Destination restricted"; string internal constant MAX_INVESTORS_IN_CATEGORY = "Max investors in category"; string internal constant ONLY_ACCREDITED = "Only accredited"; string internal constant ONLY_US_ACCREDITED = "Only us accredited"; string internal constant NOT_ENOUGH_INVESTORS = "Not enough investors"; struct CompletePreTransferCheckArgs { address from; address to; uint256 value; uint256 fromInvestorBalance; uint256 fromRegion; bool isPlatformWalletTo; } using SafeMath for uint256; function isRetail(address[] memory _services, address _wallet) internal view returns (bool) { IDSRegistryService registry = IDSRegistryService(_services[REGISTRY_SERVICE]); return !registry.isQualifiedInvestor(_wallet); } function isAccredited(address[] memory _services, address _wallet) internal view returns (bool) { IDSRegistryService registry = IDSRegistryService(_services[REGISTRY_SERVICE]); return registry.isAccreditedInvestor(_wallet); } function balanceOfInvestor(address[] memory _services, address _wallet) internal view returns (uint256) { IDSRegistryService registry = IDSRegistryService(_services[REGISTRY_SERVICE]); IDSToken token = IDSToken(_services[DS_TOKEN]); return token.balanceOfInvestor(registry.getInvestor(_wallet)); } function isNewInvestor(address[] memory _services, address _to, uint256 _balanceOfInvestorTo) internal view returns (bool) { IDSOmnibusTBEController omnibusTBEController = IDSOmnibusTBEController(_services[OMNIBUS_TBE_CONTROLLER]); // Return whether this investor has 0 balance and is not an omnibus TBE wallet return _balanceOfInvestorTo == 0 && !isOmnibusTBE(omnibusTBEController, _to); } function getCountry(address[] memory _services, address _wallet) internal view returns (string memory) { IDSRegistryService registry = IDSRegistryService(_services[REGISTRY_SERVICE]); return registry.getCountry(registry.getInvestor(_wallet)); } function getCountryCompliance(address[] memory _services, address _wallet) internal view returns (uint256) { return IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getCountryCompliance(getCountry(_services, _wallet)); } function getUSInvestorsLimit(address[] memory _services) internal view returns (uint256) { ComplianceServiceRegulated complianceService = ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]); IDSComplianceConfigurationService compConfService = IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]); if (compConfService.getMaxUSInvestorsPercentage() == 0) { return compConfService.getUSInvestorsLimit(); } if (compConfService.getUSInvestorsLimit() == 0) { return compConfService.getMaxUSInvestorsPercentage().mul(complianceService.getTotalInvestorsCount()).div(100); } return Math.min(compConfService.getUSInvestorsLimit(), compConfService.getMaxUSInvestorsPercentage().mul(complianceService.getTotalInvestorsCount()).div(100)); } function isOmnibusTBE(IDSOmnibusTBEController _omnibusTBE, address _from) public view returns (bool) { if (address(_omnibusTBE) != address(0)) { return _omnibusTBE.getOmnibusWallet() == _from; } return false; } function checkHoldUp( address[] memory _services, address _from, uint256 _value, bool _isUSLockPeriod, bool _isPlatformWalletFrom ) internal view returns (bool) { ComplianceServiceRegulated complianceService = ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]); uint64 lockPeriod; if (_isUSLockPeriod) { lockPeriod = uint64(IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getUSLockPeriod()); } else { lockPeriod = uint64(IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getNonUSLockPeriod()); } return !_isPlatformWalletFrom && complianceService.getComplianceTransferableTokens(_from, block.timestamp, lockPeriod) < _value; } function maxInvestorsInCategoryForNonAccredited( address[] memory _services, address _from, address _to, uint256 _value, uint256 fromInvestorBalance, uint256 toInvestorBalance ) internal view returns (bool) { uint256 nonAccreditedInvestorLimit = IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getNonAccreditedInvestorsLimit(); return nonAccreditedInvestorLimit != 0 && ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getTotalInvestorsCount() - ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getAccreditedInvestorsCount() >= nonAccreditedInvestorLimit && isNewInvestor(_services, _to, toInvestorBalance) && (isAccredited(_services, _from) || fromInvestorBalance > _value); } function newPreTransferCheck( address[] memory _services, address _from, address _to, uint256 _value, uint256 _balanceFrom, bool _paused ) public view returns (uint256 code, string memory reason) { return doPreTransferCheckRegulated (_services, _from, _to, _value, _balanceFrom, _paused); } function preTransferCheck( address[] memory _services, address _from, address _to, uint256 _value ) public view returns (uint256 code, string memory reason) { return doPreTransferCheckRegulated(_services, _from, _to, _value, IDSToken(_services[DS_TOKEN]).balanceOf(_from), IDSToken(_services[DS_TOKEN]).isPaused()); } function doPreTransferCheckRegulated( address[] memory _services, address _from, address _to, uint256 _value, uint256 _balanceFrom, bool _paused ) internal view returns (uint256 code, string memory reason) { if (_balanceFrom < _value) { return (15, NOT_ENOUGH_TOKENS); } uint256 fromInvestorBalance = balanceOfInvestor(_services, _from); uint256 fromRegion = getCountryCompliance(_services, _from); bool isPlatformWalletTo = IDSWalletManager(_services[WALLET_MANAGER]).isPlatformWallet(_to); if (isPlatformWalletTo) { if ( ((IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getForceFullTransfer() && (fromRegion == US)) || IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getWorldWideForceFullTransfer()) && fromInvestorBalance > _value ) { return (50, ONLY_FULL_TRANSFER); } return (0, VALID); } if (_paused && !(isOmnibusTBE(IDSOmnibusTBEController(_services[OMNIBUS_TBE_CONTROLLER]), _from))) { return (10, TOKEN_PAUSED); } CompletePreTransferCheckArgs memory args = CompletePreTransferCheckArgs(_from, _to, _value, fromInvestorBalance, fromRegion, isPlatformWalletTo); return completeTransferCheck(_services, args); } function completeTransferCheck( address[] memory _services, CompletePreTransferCheckArgs memory _args ) internal view returns (uint256 code, string memory reason) { (string memory investorFrom, string memory investorTo) = IDSRegistryService(_services[REGISTRY_SERVICE]).getInvestors(_args.from, _args.to); if ( !CommonUtils.isEmptyString(investorFrom) && CommonUtils.isEqualString(investorFrom, investorTo) ) { return (0, VALID); } if (!ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).checkWhitelisted(_args.to)) { return (20, WALLET_NOT_IN_REGISTRY_SERVICE); } uint256 toRegion = getCountryCompliance(_services, _args.to); if (toRegion == FORBIDDEN) { return (26, DESTINATION_RESTRICTED); } if (isOmnibusTBE(IDSOmnibusTBEController(_services[OMNIBUS_TBE_CONTROLLER]), _args.from)) { return(0, VALID); } bool isPlatformWalletFrom = IDSWalletManager(_services[WALLET_MANAGER]).isPlatformWallet(_args.from); if ( !isPlatformWalletFrom && IDSLockManager(_services[LOCK_MANAGER]).getTransferableTokens(_args.from, block.timestamp) < _args.value ) { return (16, TOKENS_LOCKED); } if (_args.fromRegion == US) { if (checkHoldUp(_services, _args.from, _args.value, true, isPlatformWalletFrom)) { return (32, HOLD_UP); } if ( _args.fromInvestorBalance > _args.value && _args.fromInvestorBalance - _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinUSTokens() ) { return (51, AMOUNT_OF_TOKENS_UNDER_MIN); } if ( IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getForceFullTransfer() && _args.fromInvestorBalance > _args.value ) { return (50, ONLY_FULL_TRANSFER); } } else { if (checkHoldUp(_services, _args.from, _args.value, false, isPlatformWalletFrom)) { return (33, HOLD_UP); } if ( toRegion == US && !isPlatformWalletFrom && isBlockFlowbackEndTimeOk(IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getBlockFlowbackEndTime()) ) { return (25, FLOWBACK); } if ( IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getWorldWideForceFullTransfer() && _args.fromInvestorBalance > _args.value ) { return (50, ONLY_FULL_TRANSFER); } } uint256 toInvestorBalance = balanceOfInvestor(_services, _args.to); string memory toCountry = getCountry(_services, _args.to); if (_args.fromRegion == EU) { if (_args.fromInvestorBalance - _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinEUTokens() && _args.fromInvestorBalance > _args.value) { return (51, AMOUNT_OF_TOKENS_UNDER_MIN); } } bool isAccreditedTo = isAccredited(_services, _args.to); if ( IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getForceAccredited() && !isAccreditedTo ) { return (61, ONLY_ACCREDITED); } if (toRegion == JP) { if ( IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getJPInvestorsLimit() != 0 && ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getJPInvestorsCount() >= IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getJPInvestorsLimit() && isNewInvestor(_services, _args.to, toInvestorBalance) && (!CommonUtils.isEqualString(getCountry(_services, _args.from), toCountry) || (_args.fromInvestorBalance > _args.value)) ) { return (40, MAX_INVESTORS_IN_CATEGORY); } } else if (toRegion == EU) { if ( isRetail(_services, _args.to) && ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getEURetailInvestorsCount(toCountry) >= IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getEURetailInvestorsLimit() && isNewInvestor(_services, _args.to, toInvestorBalance) && (!CommonUtils.isEqualString(getCountry(_services, _args.from), toCountry) || (_args.fromInvestorBalance > _args.value && isRetail(_services, _args.from))) ) { return (40, MAX_INVESTORS_IN_CATEGORY); } if ( toInvestorBalance + _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinEUTokens() ) { return (51, AMOUNT_OF_TOKENS_UNDER_MIN); } } else if (toRegion == US) { if ( IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getForceAccreditedUS() && !isAccreditedTo ) { return (62, ONLY_US_ACCREDITED); } uint256 usInvestorsLimit = getUSInvestorsLimit(_services); if ( usInvestorsLimit != 0 && _args.fromInvestorBalance > _args.value && ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getUSInvestorsCount() >= usInvestorsLimit && isNewInvestor(_services, _args.to, toInvestorBalance) ) { return (40, MAX_INVESTORS_IN_CATEGORY); } if ( IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getUSAccreditedInvestorsLimit() != 0 && isAccreditedTo && ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getUSAccreditedInvestorsCount() >= IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getUSAccreditedInvestorsLimit() && isNewInvestor(_services, _args.to, toInvestorBalance) && (_args.fromRegion != US || !isAccredited(_services, _args.from) || _args.fromInvestorBalance > _args.value) ) { return (40, MAX_INVESTORS_IN_CATEGORY); } if ( toInvestorBalance + _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinUSTokens() ) { return (51, AMOUNT_OF_TOKENS_UNDER_MIN); } } if (!isAccreditedTo) { if (maxInvestorsInCategoryForNonAccredited(_services, _args.from, _args.to, _args.value, _args.fromInvestorBalance, toInvestorBalance)) { return (40, MAX_INVESTORS_IN_CATEGORY); } } if ( IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getTotalInvestorsLimit() != 0 && _args.fromInvestorBalance > _args.value && ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getTotalInvestorsCount() >= IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getTotalInvestorsLimit() && isNewInvestor(_services, _args.to, toInvestorBalance) ) { return (40, MAX_INVESTORS_IN_CATEGORY); } if ( _args.fromInvestorBalance == _args.value && !isNewInvestor(_services, _args.to, toInvestorBalance) && ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getTotalInvestorsCount() <= IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinimumTotalInvestors() ) { return (71, NOT_ENOUGH_INVESTORS); } if ( !isPlatformWalletFrom && _args.fromInvestorBalance - _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinimumHoldingsPerInvestor() && _args.fromInvestorBalance > _args.value ) { return (51, AMOUNT_OF_TOKENS_UNDER_MIN); } if ( !_args.isPlatformWalletTo && toInvestorBalance + _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinimumHoldingsPerInvestor() ) { return (51, AMOUNT_OF_TOKENS_UNDER_MIN); } if ( isMaximumHoldingsPerInvestorOk( IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMaximumHoldingsPerInvestor(), toInvestorBalance, _args.value) ) { return (52, AMOUNT_OF_TOKENS_ABOVE_MAX); } return (0, VALID); } function preIssuanceCheck( address[] memory _services, address _to, uint256 _value ) public view returns (uint256 code, string memory reason) { ComplianceServiceRegulated complianceService = ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]); IDSComplianceConfigurationService complianceConfigurationService = IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]); IDSWalletManager walletManager = IDSWalletManager(_services[WALLET_MANAGER]); string memory toCountry = IDSRegistryService(_services[REGISTRY_SERVICE]).getCountry(IDSRegistryService(_services[REGISTRY_SERVICE]).getInvestor(_to)); uint256 toRegion = complianceConfigurationService.getCountryCompliance(toCountry); if (toRegion == FORBIDDEN) { return (26, DESTINATION_RESTRICTED); } if (!complianceService.checkWhitelisted(_to)) { return (20, WALLET_NOT_IN_REGISTRY_SERVICE); } uint256 balanceOfInvestorTo = balanceOfInvestor(_services, _to); if (isNewInvestor(_services, _to, balanceOfInvestorTo)) { // verify global non accredited limit if (!isAccredited(_services, _to)) { if ( complianceConfigurationService.getNonAccreditedInvestorsLimit() != 0 && complianceService.getTotalInvestorsCount() - complianceService.getAccreditedInvestorsCount() >= complianceConfigurationService.getNonAccreditedInvestorsLimit() ) { return (40, MAX_INVESTORS_IN_CATEGORY); } } // verify global investors limit if ( complianceConfigurationService.getTotalInvestorsLimit() != 0 && complianceService.getTotalInvestorsCount() >= complianceConfigurationService.getTotalInvestorsLimit() ) { return (40, MAX_INVESTORS_IN_CATEGORY); } if (toRegion == US) { // verify US investors limit is not exceeded if (complianceConfigurationService.getUSInvestorsLimit() != 0 && complianceService.getUSInvestorsCount() >= complianceConfigurationService.getUSInvestorsLimit()) { return (40, MAX_INVESTORS_IN_CATEGORY); } // verify accredited US limit is not exceeded if ( complianceConfigurationService.getUSAccreditedInvestorsLimit() != 0 && isAccredited(_services, _to) && complianceService.getUSAccreditedInvestorsCount() >= complianceConfigurationService.getUSAccreditedInvestorsLimit() ) { return (40, MAX_INVESTORS_IN_CATEGORY); } } else if (toRegion == EU) { if ( isRetail(_services, _to) && complianceService.getEURetailInvestorsCount(getCountry(_services, _to)) >= complianceConfigurationService.getEURetailInvestorsLimit() ) { return (40, MAX_INVESTORS_IN_CATEGORY); } } else if (toRegion == JP) { if (complianceConfigurationService.getJPInvestorsLimit() != 0 && complianceService.getJPInvestorsCount() >= complianceConfigurationService.getJPInvestorsLimit()) { return (40, MAX_INVESTORS_IN_CATEGORY); } } } if ( !walletManager.isPlatformWallet(_to) && balanceOfInvestorTo + _value < complianceConfigurationService.getMinimumHoldingsPerInvestor() ) { return (51, AMOUNT_OF_TOKENS_UNDER_MIN); } if (isMaximumHoldingsPerInvestorOk( complianceConfigurationService.getMaximumHoldingsPerInvestor(), balanceOfInvestorTo, _value) ) { return (52, AMOUNT_OF_TOKENS_ABOVE_MAX); } return (0, VALID); } function isMaximumHoldingsPerInvestorOk(uint256 _maximumHoldingsPerInvestor, uint256 _balanceOfInvestorTo, uint256 _value) internal pure returns (bool) { return _maximumHoldingsPerInvestor != 0 && _balanceOfInvestorTo + _value > _maximumHoldingsPerInvestor; } function isBlockFlowbackEndTimeOk(uint256 _blockFlowBackEndTime) private view returns (bool){ return (_blockFlowBackEndTime == 0 || _blockFlowBackEndTime > block.timestamp); } } /** * @title Concrete compliance service for tokens with regulation * */ //SPDX-License-Identifier: UNLICENSED contract ComplianceServiceRegulated is ComplianceServiceWhitelisted { function initialize() public virtual override initializer forceInitializeFromProxy { super.initialize(); VERSIONS.push(13); } function compareInvestorBalance( address _who, uint256 _value, uint256 _compareTo ) internal view returns (bool) { return (_value != 0 && getToken().balanceOfInvestor(getRegistryService().getInvestor(_who)) == _compareTo); } function recordTransfer( address _from, address _to, uint256 _value ) internal override returns (bool) { if (!(ComplianceServiceLibrary.isOmnibusTBE(getOmnibusTBEController(), _from) || ComplianceServiceLibrary.isOmnibusTBE(getOmnibusTBEController(), _to))) { if (compareInvestorBalance(_to, _value, 0)) { adjustTransferCounts(_to, CommonUtils.IncDec.Increase); } } return true; } function adjustTransferCounts( address _from, CommonUtils.IncDec _increase ) internal { adjustTotalInvestorsCounts(_from, _increase); } function recordIssuance( address _to, uint256 _value, uint256 _issuanceTime ) internal override returns (bool) { if (compareInvestorBalance(_to, _value, 0)) { adjustTotalInvestorsCounts(_to, CommonUtils.IncDec.Increase); } return createIssuanceInformation(getRegistryService().getInvestor(_to), _value, _issuanceTime); } function recordBurn(address /*_who*/, uint256 /*_value*/) internal pure override returns (bool) { return true; } function recordSeize( address _from, address, /*_to*/ uint256 _value ) internal pure override returns (bool) { return recordBurn(_from, _value); } function adjustInvestorCountsAfterCountryChange( string memory _id, string memory _country, string memory /*_prevCountry*/ ) public override onlyRegistry returns (bool) { if (getToken().balanceOfInvestor(_id) == 0) { return false; } adjustInvestorsCountsByCountry(_country, _id, CommonUtils.IncDec.Increase); return true; } function adjustTotalInvestorsCounts(address _wallet, CommonUtils.IncDec _increase) internal { if (!getWalletManager().isSpecialWallet(_wallet)) { if (_increase == CommonUtils.IncDec.Increase) { totalInvestors++; } string memory id = getRegistryService().getInvestor(_wallet); string memory country = getRegistryService().getCountry(id); adjustInvestorsCountsByCountry(country, id, _increase); } } function adjustInvestorsCountsByCountry( string memory _country, string memory _id, CommonUtils.IncDec _increase ) internal { uint256 countryCompliance = getComplianceConfigurationService().getCountryCompliance(_country); if (getRegistryService().isAccreditedInvestor(_id)) { if(_increase == CommonUtils.IncDec.Increase) { accreditedInvestorsCount++; } if (countryCompliance == US) { if(_increase == CommonUtils.IncDec.Increase) { usAccreditedInvestorsCount++; } } } if (countryCompliance == US) { if(_increase == CommonUtils.IncDec.Increase) { usInvestorsCount++; } } else if (countryCompliance == EU && !getRegistryService().isQualifiedInvestor(_id)) { if(_increase == CommonUtils.IncDec.Increase) { euRetailInvestorsCount[_country]++; } } else if (countryCompliance == JP) { if(_increase == CommonUtils.IncDec.Increase) { jpInvestorsCount++; } } } function createIssuanceInformation( string memory _investor, uint256 _value, uint256 _issuanceTime ) internal returns (bool) { uint256 issuancesCount = issuancesCounters[_investor]; issuancesValues[_investor][issuancesCount] = _value; issuancesTimestamps[_investor][issuancesCount] = _issuanceTime; issuancesCounters[_investor] = issuancesCount + 1; return true; } function preTransferCheck( address _from, address _to, uint256 _value ) public view virtual override returns (uint256 code, string memory reason) { return ComplianceServiceLibrary.preTransferCheck(getServices(), _from, _to, _value); } function newPreTransferCheck( address _from, address _to, uint256 _value, uint256 _balanceFrom, bool _pausedToken ) public view virtual override returns (uint256 code, string memory reason) { return ComplianceServiceLibrary.newPreTransferCheck(getServices(), _from, _to, _value, _balanceFrom, _pausedToken); } function preInternalTransferCheck( address _from, address _to, uint256 _value) public view override returns (uint256 code, string memory reason) { return ComplianceServiceLibrary.preTransferCheck(getServices(), _from, _to, _value); } function getComplianceTransferableTokens( address _who, uint256 _time, uint64 _lockTime ) public view returns (uint256) { require(_time != 0, "Time must be greater than zero"); string memory investor = getRegistryService().getInvestor(_who); uint256 balanceOfInvestor = getLockManager().getTransferableTokens(_who, _time); uint256 investorIssuancesCount = issuancesCounters[investor]; //No locks, go to base class implementation if (investorIssuancesCount == 0) { return balanceOfInvestor; } uint256 totalLockedTokens = 0; for (uint256 i = 0; i < investorIssuancesCount; i++) { uint256 issuanceTimestamp = issuancesTimestamps[investor][i]; if (_lockTime > _time || issuanceTimestamp > SafeMath.sub(_time, _lockTime)) { totalLockedTokens = totalLockedTokens + issuancesValues[investor][i]; } } //there may be more locked tokens than actual tokens, so the minimum between the two uint256 transferable = SafeMath.sub(balanceOfInvestor, Math.min(totalLockedTokens, balanceOfInvestor)); return transferable; } function preIssuanceCheck(address _to, uint256 _value) public view override returns (uint256 code, string memory reason) { return ComplianceServiceLibrary.preIssuanceCheck(getServices(), _to, _value); } function getTotalInvestorsCount() public view returns (uint256) { return totalInvestors; } function getUSInvestorsCount() public view returns (uint256) { return usInvestorsCount; } function getUSAccreditedInvestorsCount() public view returns (uint256) { return usAccreditedInvestorsCount; } function getAccreditedInvestorsCount() public view returns (uint256) { return accreditedInvestorsCount; } function getEURetailInvestorsCount(string memory _country) public view returns (uint256) { return euRetailInvestorsCount[_country]; } function getJPInvestorsCount() public view returns (uint256) { return jpInvestorsCount; } function setTotalInvestorsCount(uint256 _value) public onlyMasterOrTBEOmnibus returns (bool) { totalInvestors = _value; return true; } function setUSInvestorsCount(uint256 _value) public onlyMasterOrTBEOmnibus returns (bool) { usInvestorsCount = _value; return true; } function setUSAccreditedInvestorsCount(uint256 _value) public onlyMasterOrTBEOmnibus returns (bool) { usAccreditedInvestorsCount = _value; return true; } function setAccreditedInvestorsCount(uint256 _value) public onlyMasterOrTBEOmnibus returns (bool) { accreditedInvestorsCount = _value; return true; } function setEURetailInvestorsCount(string memory _country, uint256 _value) public onlyMasterOrTBEOmnibus returns (bool) { euRetailInvestorsCount[_country] = _value; return true; } function setJPInvestorsCount(uint256 _value) public onlyMasterOrTBEOmnibus returns (bool) { jpInvestorsCount = _value; return true; } function getServices() internal view returns (address[] memory services) { services = new address[](7); services[0] = getDSService(DS_TOKEN); services[1] = getDSService(REGISTRY_SERVICE); services[2] = getDSService(WALLET_MANAGER); services[3] = getDSService(COMPLIANCE_CONFIGURATION_SERVICE); services[4] = getDSService(LOCK_MANAGER); services[5] = address(this); services[6] = getDSService(OMNIBUS_TBE_CONTROLLER); } }
pragma solidity ^0.8.13; import "./ComplianceService.sol"; import "../registry/IDSRegistryService.sol"; /** * @title Concrete compliance service for tokens with whitelisted wallets. * * This simple compliance service is meant to be used for tokens that only need to be validated against an investor registry. */ //SPDX-License-Identifier: UNLICENSED contract ComplianceServiceWhitelisted is ComplianceService { function initialize() public virtual override initializer forceInitializeFromProxy { ComplianceService.initialize(); VERSIONS.push(5); } function newPreTransferCheck( address _from, address _to, uint256 _value, uint256 _balanceFrom, bool _pausedToken ) public view virtual override returns (uint256 code, string memory reason) { return doPreTransferCheckWhitelisted(_from, _to, _value, _balanceFrom, _pausedToken); } function preTransferCheck( address _from, address _to, uint256 _value ) public view virtual override returns (uint256 code, string memory reason) { return doPreTransferCheckWhitelisted(_from, _to, _value, getToken().balanceOf(_from), getToken().isPaused()); } function checkWhitelisted(address _who) public view returns (bool) { return getWalletManager().isPlatformWallet(_who) || !CommonUtils.isEmptyString(getRegistryService().getInvestor(_who)); } function recordIssuance(address, uint256, uint256) internal virtual override returns (bool) { return true; } function recordTransfer(address, address, uint256) internal virtual override returns (bool) { return true; } function checkTransfer(address, address _to, uint256) internal view override returns (uint256, string memory) { if (!checkWhitelisted(_to)) { return (20, WALLET_NOT_IN_REGISTRY_SERVICE); } return (0, VALID); } function preIssuanceCheck(address _to, uint256) public view virtual override returns (uint256, string memory) { if (!checkWhitelisted(_to)) { return (20, WALLET_NOT_IN_REGISTRY_SERVICE); } return (0, VALID); } function recordBurn(address, uint256) internal virtual override returns (bool) { return true; } function recordSeize(address, address, uint256) internal virtual override returns (bool) { return true; } function doPreTransferCheckWhitelisted( address _from, address _to, uint256 _value, uint256 _balanceFrom, bool _pausedToken ) internal view returns (uint256 code, string memory reason) { if (_pausedToken) { return (10, TOKEN_PAUSED); } if (_balanceFrom < _value) { return (15, NOT_ENOUGH_TOKENS); } if (!getWalletManager().isPlatformWallet(_from) && getLockManager().getTransferableTokens(_from, block.timestamp) < _value) { return (16, TOKENS_LOCKED); } return checkTransfer(_from, _to, _value); } }
pragma solidity ^0.8.13; import "../utils/VersionedContract.sol"; import "../utils/Initializable.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSComplianceConfigurationService is Initializable, VersionedContract { function initialize() public virtual { VERSIONS.push(7); } event DSComplianceUIntRuleSet(string ruleName, uint256 prevValue, uint256 newValue); event DSComplianceBoolRuleSet(string ruleName, bool prevValue, bool newValue); event DSComplianceStringToUIntMapRuleSet(string ruleName, string keyValue, uint256 prevValue, uint256 newValue); function getCountryCompliance(string memory _country) public view virtual returns (uint256); function setCountriesCompliance(string[] memory _countries, uint256[] memory _values) public virtual; function setCountryCompliance( string memory _country, uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getTotalInvestorsLimit() public view virtual returns (uint256); function setTotalInvestorsLimit( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getMinUSTokens() public view virtual returns (uint256); function setMinUSTokens( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getMinEUTokens() public view virtual returns (uint256); function setMinEUTokens( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getUSInvestorsLimit() public view virtual returns (uint256); function setUSInvestorsLimit( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getJPInvestorsLimit() public view virtual returns (uint256); function setJPInvestorsLimit( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getUSAccreditedInvestorsLimit() public view virtual returns (uint256); function setUSAccreditedInvestorsLimit( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getNonAccreditedInvestorsLimit() public view virtual returns (uint256); function setNonAccreditedInvestorsLimit( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getMaxUSInvestorsPercentage() public view virtual returns (uint256); function setMaxUSInvestorsPercentage( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getBlockFlowbackEndTime() public view virtual returns (uint256); function setBlockFlowbackEndTime( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getNonUSLockPeriod() public view virtual returns (uint256); function setNonUSLockPeriod( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getMinimumTotalInvestors() public view virtual returns (uint256); function setMinimumTotalInvestors( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getMinimumHoldingsPerInvestor() public view virtual returns (uint256); function setMinimumHoldingsPerInvestor( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getMaximumHoldingsPerInvestor() public view virtual returns (uint256); function setMaximumHoldingsPerInvestor( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getEURetailInvestorsLimit() public view virtual returns (uint256); function setEURetailInvestorsLimit( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getUSLockPeriod() public view virtual returns (uint256); function setUSLockPeriod( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getForceFullTransfer() public view virtual returns (bool); function setForceFullTransfer( bool _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getForceAccredited() public view virtual returns (bool); function setForceAccredited( bool _value /*onlyTransferAgentOrAbove*/ ) public virtual; function setForceAccreditedUS( bool _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getForceAccreditedUS() public view virtual returns (bool); function setWorldWideForceFullTransfer( bool _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getWorldWideForceFullTransfer() public view virtual returns (bool); function getAuthorizedSecurities() public view virtual returns (uint256); function setAuthorizedSecurities( uint256 _value /*onlyTransferAgentOrAbove*/ ) public virtual; function getDisallowBackDating() public view virtual returns (bool); function setDisallowBackDating( bool _value /*onlyTransferAgentOrAbove*/ ) public virtual; function setAll( uint256[] memory _uint_values, bool[] memory _bool_values /*onlyTransferAgentOrAbove*/ ) public virtual; function getAll() public view virtual returns (uint256[] memory, bool[] memory); }
pragma solidity ^0.8.13; import "../utils/VersionedContract.sol"; import "../utils/Initializable.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSComplianceService is Initializable, VersionedContract { function initialize() public virtual { VERSIONS.push(7); } uint256 internal constant NONE = 0; uint256 internal constant US = 1; uint256 internal constant EU = 2; uint256 internal constant FORBIDDEN = 4; uint256 internal constant JP = 8; string internal constant TOKEN_PAUSED = "Token Paused"; string internal constant NOT_ENOUGH_TOKENS = "Not Enough Tokens"; string internal constant TOKENS_LOCKED = "Tokens Locked"; string internal constant WALLET_NOT_IN_REGISTRY_SERVICE = "Wallet not in registry Service"; string internal constant DESTINATION_RESTRICTED = "Destination restricted"; string internal constant VALID = "Valid"; string internal constant HOLD_UP = "Under lock-up"; string internal constant ONLY_FULL_TRANSFER = "Only Full Transfer"; string internal constant FLOWBACK = "Flowback"; string internal constant MAX_INVESTORS_IN_CATEGORY = "Max Investors in category"; string internal constant AMOUNT_OF_TOKENS_UNDER_MIN = "Amount of tokens under min"; string internal constant AMOUNT_OF_TOKENS_ABOVE_MAX = "Amount of tokens above max"; string internal constant ONLY_ACCREDITED = "Only accredited"; string internal constant ONLY_US_ACCREDITED = "Only us accredited"; string internal constant NOT_ENOUGH_INVESTORS = "Not enough investors"; string internal constant MAX_AUTHORIZED_SECURITIES_EXCEEDED = "Max authorized securities exceeded"; function adjustInvestorCountsAfterCountryChange( string memory _id, string memory _country, string memory _prevCountry ) public virtual returns (bool); //***************************************** // TOKEN ACTION VALIDATIONS //***************************************** function validateTransfer( address _from, address _to, uint256 _value /*onlyToken*/ ) public virtual returns (bool); function validateTransfer( address _from, address _to, uint256 _value, /*onlyToken*/ bool _pausedToken, uint256 _balanceFrom ) public virtual returns (bool); function validateIssuance( address _to, uint256 _value, uint256 _issuanceTime /*onlyToken*/ ) public virtual returns (bool); function validateIssuanceWithNoCompliance( address _to, uint256 _value, uint256 _issuanceTime /*onlyToken*/ ) public virtual returns (bool); function validateBurn( address _who, uint256 _value /*onlyToken*/ ) public virtual returns (bool); function validateSeize( address _from, address _to, uint256 _value /*onlyToken*/ ) public virtual returns (bool); function preIssuanceCheck(address _to, uint256 _value) public view virtual returns (uint256 code, string memory reason); function preTransferCheck( address _from, address _to, uint256 _value ) public view virtual returns (uint256 code, string memory reason); function preInternalTransferCheck( address _from, address _to, uint256 _value ) public view virtual returns (uint256 code, string memory reason); function validateIssuanceTime(uint256 _issuanceTime) public view virtual returns (uint256 issuanceTime); }
pragma solidity ^0.8.13; import "./IDSComplianceService.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSComplianceServicePartitioned is IDSComplianceService { function initialize() public virtual override { VERSIONS.push(2); } function getComplianceTransferableTokens( address _who, uint256 _time, bool _checkFlowback ) public view virtual returns (uint256 transferable); function getComplianceTransferableTokens( address _who, uint256 _time, bool _checkFlowback, bytes32 _partition ) public view virtual returns (uint256); function getComplianceTransferableTokens( address _who, uint256 _time, address _to ) public view virtual returns (uint256 transferable); function getComplianceTransferableTokens( address _who, uint256 _time, address _to, bytes32 _partition ) public view virtual returns (uint256); }
pragma solidity ^0.8.13; import "../utils/VersionedContract.sol"; import "../utils/Initializable.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSLockManager is Initializable, VersionedContract { function initialize() public virtual; modifier validLock(uint256 _valueLocked, uint256 _releaseTime) { require(_valueLocked > 0, "Value is zero"); require(_releaseTime == 0 || _releaseTime > uint256(block.timestamp), "Release time is in the past"); _; } event Locked(address indexed who, uint256 value, uint256 indexed reason, string reasonString, uint256 releaseTime); event Unlocked(address indexed who, uint256 value, uint256 indexed reason, string reasonString, uint256 releaseTime); event HolderLocked(string holderId, uint256 value, uint256 indexed reason, string reasonString, uint256 releaseTime); event HolderUnlocked(string holderId, uint256 value, uint256 indexed reason, string reasonString, uint256 releaseTime); /** * @dev creates a lock record for wallet address * @param _to address to lock the tokens at * @param _valueLocked value of tokens to lock * @param _reason reason for lock * @param _releaseTime timestamp to release the lock (or 0 for locks which can only released by an unlockTokens call) * Note: The user MAY have at a certain time more locked tokens than actual tokens */ function addManualLockRecord( address _to, uint256 _valueLocked, string memory _reason, uint256 _releaseTime /*issuerOrAboveOrToken*/ ) public virtual; /** * @dev creates a lock record for investor Id * @param _investor investor id to lock the tokens at * @param _valueLocked value of tokens to lock * @param _reasonCode reason code for lock * @param _reasonString reason for lock * @param _releaseTime timestamp to release the lock (or 0 for locks which can only released by an unlockTokens call) * Note: The user MAY have at a certain time more locked tokens than actual tokens */ function createLockForInvestor( string memory _investor, uint256 _valueLocked, uint256 _reasonCode, string memory _reasonString, uint256 _releaseTime /*onlyIssuerOrAboveOrToken*/ ) public virtual; /** * @dev Releases a specific lock record for a wallet * @param _to address to release the tokens for * @param _lockIndex the index of the lock to remove * * note - this may change the order of the locks on an address, so if iterating the iteration should be restarted. * @return true on success */ function removeLockRecord( address _to, uint256 _lockIndex /*issuerOrAbove*/ ) public virtual returns (bool); /** * @dev Releases a specific lock record for a investor * @param _investorId investor id to release the tokens for * @param _lockIndex the index of the lock to remove * * note - this may change the order of the locks on an address, so if iterating the iteration should be restarted. * @return true on success */ function removeLockRecordForInvestor( string memory _investorId, uint256 _lockIndex /*onlyIssuerOrAbove*/ ) public virtual returns (bool); /** * @dev Get number of locks currently associated with an address * @param _who address to get count for * * @return number of locks * * Note - a lock can be inactive (due to its time expired) but still exists for a specific address */ function lockCount(address _who) public view virtual returns (uint256); /** * @dev Get number of locks currently associated with a investor * @param _investorId investor id to get count for * * @return number of locks * * Note - a lock can be inactive (due to its time expired) but still exists for a specific address */ function lockCountForInvestor(string memory _investorId) public view virtual returns (uint256); /** * @dev Get details of a specific lock associated with an address * can be used to iterate through the locks of a user * @param _who address to get token lock for * @param _lockIndex the 0 based index of the lock. * @return reasonCode the reason code * @return reasonString the reason for the lock * @return value the value of tokens locked * @return autoReleaseTime the timestamp in which the lock will be inactive (or 0 if it's always active until removed) * * Note - a lock can be inactive (due to its time expired) but still exists for a specific address */ function lockInfo(address _who, uint256 _lockIndex) public view virtual returns (uint256 reasonCode, string memory reasonString, uint256 value, uint256 autoReleaseTime); /** * @dev Get details of a specific lock associated with a investor * can be used to iterate through the locks of a user * @param _investorId investorId to get token lock for * @param _lockIndex the 0 based index of the lock. * @return reasonCode the reason code * @return reasonString the reason for the lock * @return value the value of tokens locked * @return autoReleaseTime the timestamp in which the lock will be inactive (or 0 if it's always active until removed) * * Note - a lock can be inactive (due to its time expired) but still exists for a specific address */ function lockInfoForInvestor( string memory _investorId, uint256 _lockIndex ) public view virtual returns (uint256 reasonCode, string memory reasonString, uint256 value, uint256 autoReleaseTime); /** * @dev get total number of transferable tokens for a wallet, at a certain time * @param _who address to get number of transferable tokens for * @param _time time to calculate for */ function getTransferableTokens(address _who, uint256 _time) public view virtual returns (uint256); /** * @dev get total number of transferable tokens for a investor, at a certain time * @param _investorId investor id * @param _time time to calculate for */ function getTransferableTokensForInvestor(string memory _investorId, uint256 _time) public view virtual returns (uint256); /** * @dev pause investor * @param _investorId investor id */ function lockInvestor( string memory _investorId /*issuerOrAbove*/ ) public virtual returns (bool); /** * @dev unpauses investor * @param _investorId investor id */ function unlockInvestor( string memory _investorId /*issuerOrAbove*/ ) public virtual returns (bool); /** * @dev Returns true if paused, otherwise false * @param _investorId investor id */ function isInvestorLocked(string memory _investorId) public view virtual returns (bool); }
pragma solidity ^0.8.13; import "./IDSLockManager.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSLockManagerPartitioned is Initializable, VersionedContract { event LockedPartition(address indexed who, uint256 value, uint256 indexed reason, string reasonString, uint256 releaseTime, bytes32 indexed partition); event UnlockedPartition(address indexed who, uint256 value, uint256 indexed reason, string reasonString, uint256 releaseTime, bytes32 indexed partition); event HolderLockedPartition(string investorId, uint256 value, uint256 indexed reason, string reasonString, uint256 releaseTime, bytes32 indexed partition); event HolderUnlockedPartition(string investorId, uint256 value, uint256 indexed reason, string reasonString, uint256 releaseTime, bytes32 indexed partition); function createLockForInvestor( string memory _investorId, uint256 _valueLocked, uint256 _reasonCode, string memory _reasonString, uint256 _releaseTime, bytes32 _partition ) public virtual; function addManualLockRecord( address _to, uint256 _valueLocked, string memory _reason, uint256 _releaseTime, bytes32 _partition /*issuerOrAboveOrToken*/ ) public virtual; function removeLockRecord( address _to, uint256 _lockIndex, bytes32 _partition /*issuerOrAbove*/ ) public virtual returns (bool); function removeLockRecordForInvestor( string memory _investorId, uint256 _lockIndex, bytes32 _partition /*issuerOrAbove*/ ) public virtual returns (bool); function lockCount(address _who, bytes32 _partition) public view virtual returns (uint256); function lockInfo( address _who, uint256 _lockIndex, bytes32 _partition ) public view virtual returns ( uint256 reasonCode, string memory reasonString, uint256 value, uint256 autoReleaseTime ); function lockCountForInvestor(string memory _investorId, bytes32 _partition) public view virtual returns (uint256); function lockInfoForInvestor( string memory _investorId, uint256 _lockIndex, bytes32 _partition ) public view virtual returns ( uint256 reasonCode, string memory reasonString, uint256 value, uint256 autoReleaseTime ); function getTransferableTokens( address _who, uint256 _time, bytes32 _partition ) public view virtual returns (uint256); function getTransferableTokensForInvestor( string memory _investorId, uint256 _time, bytes32 _partition ) public view virtual returns (uint256); /*************** Legacy functions ***************/ function createLockForHolder( string memory _investorId, uint256 _valueLocked, uint256 _reasonCode, string memory _reasonString, uint256 _releaseTime, bytes32 _partition ) public virtual; function removeLockRecordForHolder( string memory _investorId, uint256 _lockIndex, bytes32 _partition ) public virtual returns (bool); function lockCountForHolder(string memory _holderId, bytes32 _partition) public view virtual returns (uint256); function lockInfoForHolder( string memory _holderId, uint256 _lockIndex, bytes32 _partition ) public view virtual returns ( uint256 reasonCode, string memory reasonString, uint256 value, uint256 autoReleaseTime ); function getTransferableTokensForHolder( string memory _holderId, uint256 _time, bytes32 _partition ) public view virtual returns (uint256); /******************************/ }
pragma solidity ^0.8.13; import "../service/IDSServiceConsumer.sol"; import "../utils/Initializable.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSPartitionsManager is Initializable, IDSServiceConsumer { event PartitionCreated(uint256 _date, uint256 _region, bytes32 _partition); function initialize() public virtual override { VERSIONS.push(2); } function ensurePartition( uint256 _issuanceDate, uint256 _region /*onlyIssuerOrAboveOrToken*/ ) public virtual returns (bytes32 partition); function getPartition(bytes32 _partition) public view virtual returns (uint256 date, uint256 region); function getPartitionIssuanceDate(bytes32 _partition) public view virtual returns (uint256); function getPartitionRegion(bytes32 _partition) public view virtual returns (uint256); }
pragma solidity ^0.8.13; import "../utils/VersionedContract.sol"; import "../utils/Initializable.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSWalletManager is Initializable, VersionedContract { function initialize() public virtual { VERSIONS.push(5); } // Special wallets constants uint8 public constant NONE = 0; uint8 public constant ISSUER = 1; uint8 public constant PLATFORM = 2; uint8 public constant EXCHANGE = 4; /** * @dev should be emitted when a special wallet is added. */ event DSWalletManagerSpecialWalletAdded(address wallet, uint8 walletType, address sender); /** * @dev should be emitted when a special wallet is removed. */ event DSWalletManagerSpecialWalletRemoved(address wallet, uint8 walletType, address sender); /** * @dev should be emitted when the number of reserved slots is set for a wallet. */ event DSWalletManagerReservedSlotsSet(address wallet, string country, uint8 accreditationStatus, uint256 slots, address sender); /** * @dev Sets a wallet to be an special wallet. (internal) * @param _wallet The address of the wallet. * @param _type The type of the wallet. * @return A boolean that indicates if the operation was successful. */ function setSpecialWallet(address _wallet, uint8 _type) internal virtual returns (bool); /** * @dev gets a wallet type * @param _wallet the address of the wallet to check. */ function getWalletType(address _wallet) public view virtual returns (uint8); /** * @dev Returns true if it is platform wallet * @param _wallet the address of the wallet to check. */ function isPlatformWallet(address _wallet) external view virtual returns (bool); /** * @dev Returns true if it is special wallet * @param _wallet the address of the wallet to check. */ function isSpecialWallet(address _wallet) external view virtual returns (bool); /** * @dev Returns true if it is issuer special wallet * @param _wallet the address of the wallet to check. */ function isIssuerSpecialWallet(address _wallet) external view virtual returns (bool); /** * @dev Sets a wallet to be an issuer wallet. * @param _wallet The address of the wallet. * @return A boolean that indicates if the operation was successful. */ function addIssuerWallet( address _wallet /*onlyIssuerOrAbove*/ ) public virtual returns (bool); /** * @dev Sets an array of wallets to be issuer wallets. * @param _wallets The address of the wallets. * @return A boolean that indicates if the operation was successful. */ function addIssuerWallets(address[] memory _wallets) public virtual returns (bool); /** * @dev Sets a wallet to be a platform wallet. * @param _wallet The address of the wallet. * @return A boolean that indicates if the operation was successful. */ function addPlatformWallet( address _wallet /*onlyIssuerOrAbove*/ ) public virtual returns (bool); /** * @dev Sets an array of wallets to be platforms wallet. * @param _wallets The address of the wallets. * @return A boolean that indicates if the operation was successful. */ function addPlatformWallets(address[] memory _wallets) public virtual returns (bool); /** * @dev Sets a wallet to be an exchange wallet. * @param _wallet The address of the wallet. * @param _owner The address of the owner. * @return A boolean that indicates if the operation was successful. */ function addExchangeWallet(address _wallet, address _owner) public virtual returns (bool); /** * @dev Removes a special wallet. * @param _wallet The address of the wallet. * @return A boolean that indicates if the operation was successful. */ function removeSpecialWallet( address _wallet /*onlyIssuerOrAbove*/ ) public virtual returns (bool); }
pragma solidity ^0.8.13; import "./ServiceConsumerDataStore.sol"; //SPDX-License-Identifier: UNLICENSED contract ComplianceConfigurationDataStore is ServiceConsumerDataStore { mapping(string => uint256) public countriesCompliances; uint256 public totalInvestorsLimit; uint256 public minUSTokens; uint256 public minEUTokens; uint256 public usInvestorsLimit; uint256 public jpInvestorsLimit; uint256 public usAccreditedInvestorsLimit; uint256 public nonAccreditedInvestorsLimit; uint256 public maxUSInvestorsPercentage; uint256 public blockFlowbackEndTime; uint256 public nonUSLockPeriod; uint256 public minimumTotalInvestors; uint256 public minimumHoldingsPerInvestor; uint256 public maximumHoldingsPerInvestor; uint256 public euRetailInvestorsLimit; uint256 public usLockPeriod; bool public forceFullTransfer; bool public forceAccreditedUS; bool public forceAccredited; bool public worldWideForceFullTransfer; uint256 public authorizedSecurities; bool public disallowBackDating; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[45] private __gap; }
pragma solidity ^0.8.13; import "./ServiceConsumerDataStore.sol"; //SPDX-License-Identifier: UNLICENSED contract ComplianceServiceDataStore is ServiceConsumerDataStore { uint256 internal totalInvestors; uint256 internal accreditedInvestorsCount; uint256 internal usAccreditedInvestorsCount; uint256 internal usInvestorsCount; uint256 internal jpInvestorsCount; mapping(string => uint256) internal euRetailInvestorsCount; mapping(string => uint256) internal issuancesCounters; mapping(string => mapping(uint256 => uint256)) issuancesValues; mapping(string => mapping(uint256 => uint256)) issuancesTimestamps; }
pragma solidity ^0.8.13; import "./ServiceConsumerDataStore.sol"; //SPDX-License-Identifier: UNLICENSED contract OmnibusTBEControllerDataStore is ServiceConsumerDataStore { address internal omnibusWallet; bool internal isPartitionedToken; }
pragma solidity ^0.8.13; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; //SPDX-License-Identifier: UNLICENSED contract ServiceConsumerDataStore { using SafeMath for uint256; mapping(uint256 => address) internal services; }
pragma solidity ^0.8.13; import "./ServiceConsumerDataStore.sol"; import '../token/TokenPartitionsLibrary.sol'; import '../token/TokenLibrary.sol'; //SPDX-License-Identifier: UNLICENSED contract TokenDataStore is ServiceConsumerDataStore { TokenLibrary.TokenData internal tokenData; mapping(address => mapping(address => uint256)) internal allowances; mapping(uint256 => address) internal walletsList; uint256 internal walletsCount; mapping(address => uint256) internal walletsToIndexes; TokenPartitionsLibrary.TokenPartitions internal partitionsManagement; uint256 public cap; string public name; string public symbol; uint8 public decimals; TokenLibrary.SupportedFeatures public supportedFeatures; bool internal paused; }
pragma solidity ^0.8.13; import "../service/ServiceConsumer.sol"; import "../utils/ProxyTarget.sol"; import "../data-stores/OmnibusTBEControllerDataStore.sol"; import "../utils/VersionedContract.sol"; import "../utils/Initializable.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSOmnibusTBEController is Initializable, VersionedContract { using SafeMath for uint256; function initialize(address _omnibusWallet, bool _isPartitionedToken) public virtual; function bulkIssuance(uint256 value, uint256 issuanceTime, uint256 totalInvestors, uint256 accreditedInvestors, uint256 usAccreditedInvestors, uint256 usTotalInvestors, uint256 jpTotalInvestors, bytes32[] memory euRetailCountries, uint256[] memory euRetailCountryCounts) public virtual; function bulkBurn(uint256 value, uint256 totalInvestors, uint256 accreditedInvestors, uint256 usAccreditedInvestors, uint256 usTotalInvestors, uint256 jpTotalInvestors, bytes32[] memory euRetailCountries, uint256[] memory euRetailCountryCounts) public virtual; function bulkTransfer(address[] memory wallets, uint256[] memory values) public virtual; function adjustCounters(int256 totalDelta, int256 accreditedDelta, int256 usAccreditedDelta, int256 usTotalDelta, int256 jpTotalDelta, bytes32[] memory euRetailCountries, int256[] memory euRetailCountryDeltas) public virtual; function getOmnibusWallet() public view virtual returns (address); }
pragma solidity ^0.8.13; import "../utils/VersionedContract.sol"; import "../utils/Initializable.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSOmnibusWalletController is Initializable, VersionedContract { uint8 public constant BENEFICIARY = 0; uint8 public constant HOLDER_OF_RECORD = 1; function initialize(address _omnibusWallet) public virtual; function setAssetTrackingMode(uint8 _assetTrackingMode) public virtual; function getAssetTrackingMode() public view virtual returns (uint8); function isHolderOfRecord() public view virtual returns (bool); function balanceOf(address _who) public view virtual returns (uint256); function transfer( address _from, address _to, uint256 _value /*onlyOperator*/ ) public virtual; function deposit( address _to, uint256 _value /*onlyToken*/ ) public virtual; function withdraw( address _from, uint256 _value /*onlyToken*/ ) public virtual; function seize( address _from, uint256 _value /*onlyToken*/ ) public virtual; function burn( address _from, uint256 _value /*onlyToken*/ ) public virtual; }
pragma solidity ^0.8.13; import "../service/ServiceConsumer.sol"; import "../utils/ProxyTarget.sol"; import "../data-stores/OmnibusTBEControllerDataStore.sol"; import "../compliance/ComplianceServiceRegulated.sol"; import "../compliance/ComplianceConfigurationService.sol"; //SPDX-License-Identifier: UNLICENSED contract OmnibusTBEController is ProxyTarget, Initializable, IDSOmnibusTBEController, ServiceConsumer, OmnibusTBEControllerDataStore { using SafeMath for uint256; string internal constant MAX_INVESTORS_IN_CATEGORY = "Max investors in category"; function initialize(address _omnibusWallet, bool _isPartitionedToken) public override initializer forceInitializeFromProxy { VERSIONS.push(4); ServiceConsumer.initialize(); omnibusWallet = _omnibusWallet; isPartitionedToken = _isPartitionedToken; } function bulkIssuance(uint256 value, uint256 issuanceTime, uint256 totalInvestors, uint256 accreditedInvestors, uint256 usAccreditedInvestors, uint256 usTotalInvestors, uint256 jpTotalInvestors, bytes32[] memory euRetailCountries, uint256[] memory euRetailCountryCounts) public override onlyIssuerOrAbove { require(euRetailCountries.length == euRetailCountryCounts.length, 'EU Retail countries arrays do not match'); // Issue tokens getToken().issueTokensCustom(omnibusWallet, value, issuanceTime, 0, '', 0); addToCounters(totalInvestors, accreditedInvestors, usAccreditedInvestors, usTotalInvestors, jpTotalInvestors, euRetailCountries, euRetailCountryCounts, true); emitTBEOperationEvent(totalInvestors, accreditedInvestors, usAccreditedInvestors, usTotalInvestors, jpTotalInvestors, true); } function bulkBurn(uint256 value, uint256 totalInvestors, uint256 accreditedInvestors, uint256 usAccreditedInvestors, uint256 usTotalInvestors, uint256 jpTotalInvestors, bytes32[] memory euRetailCountries, uint256[] memory euRetailCountryCounts) public override onlyTransferAgentOrAbove { require(euRetailCountries.length == euRetailCountryCounts.length, 'EU Retail countries arrays do not match'); if(isPartitionedToken) { IDSTokenPartitioned token = getTokenPartitioned(); uint256 pendingBurn = value; uint256 currentPartitionBalance; bytes32 partition; while(pendingBurn > 0) { require(token.partitionCountOf(omnibusWallet) > 0, 'Not enough tokens in partitions to burn the required value'); partition = token.partitionOf(omnibusWallet, 0); currentPartitionBalance = token.balanceOfByPartition(omnibusWallet, partition); require(currentPartitionBalance > 0, 'Not enough tokens in remaining partitions to burn the required value'); uint256 amountToBurn = currentPartitionBalance >= pendingBurn ? pendingBurn : currentPartitionBalance; token.burnByPartition(omnibusWallet, amountToBurn, 'Omnibus burn by partition', partition); pendingBurn = pendingBurn - amountToBurn; } } else { // Burn non partitioned tokens getToken().burn(omnibusWallet, value, 'Omnibus'); } emitTBEOperationEvent(totalInvestors, accreditedInvestors, usAccreditedInvestors, usTotalInvestors, jpTotalInvestors, false); } function bulkTransfer(address[] memory wallets, uint256[] memory values) public override onlyIssuerOrTransferAgentOrAbove { require(wallets.length == values.length, 'Wallets and values lengths do not match'); for (uint i = 0; i < wallets.length; i++) { getToken().transferFrom(omnibusWallet, wallets[i], values[i]); } } function internalTBETransfer(string memory externalId, int256 totalDelta, int256 accreditedDelta, int256 usAccreditedDelta, int256 usTotalDelta, int256 jpTotalDelta, bytes32[] memory euRetailCountries, int256[] memory euRetailCountryDeltas) public onlyIssuerOrTransferAgentOrAbove { adjustCounters(totalDelta, accreditedDelta, usAccreditedDelta, usTotalDelta, jpTotalDelta, euRetailCountries, euRetailCountryDeltas); getToken().emitOmnibusTBETransferEvent(omnibusWallet, externalId); } function adjustCounters(int256 totalDelta, int256 accreditedDelta, int256 usAccreditedDelta, int256 usTotalDelta, int256 jpTotalDelta, bytes32[] memory euRetailCountries, int256[] memory euRetailCountryDeltas) public override onlyIssuerOrTransferAgentOrAbove { require(euRetailCountries.length == euRetailCountryDeltas.length, 'Array lengths do not match'); addToCounters( totalDelta > 0 ? uint256(totalDelta) : 0, accreditedDelta > 0 ? uint256(accreditedDelta) : 0, usAccreditedDelta > 0 ? uint256(usAccreditedDelta) : 0, usTotalDelta > 0 ? uint256(usTotalDelta) : 0, jpTotalDelta > 0 ? uint256(jpTotalDelta) : 0, euRetailCountries, getUintEuCountriesDeltas(euRetailCountryDeltas, true), true ); getToken().emitOmnibusTBEEvent( omnibusWallet, totalDelta, accreditedDelta, usAccreditedDelta, usTotalDelta, jpTotalDelta); } function getOmnibusWallet() public view override returns (address) { return omnibusWallet; } function addToCounters(uint256 _totalInvestors, uint256 _accreditedInvestors, uint256 _usAccreditedInvestors, uint256 _usTotalInvestors, uint256 _jpTotalInvestors, bytes32[] memory _euRetailCountries, uint256[] memory _euRetailCountryCounts, bool _increase) internal returns (bool) { if(_increase) { ComplianceServiceRegulated cs = ComplianceServiceRegulated(getDSService(COMPLIANCE_SERVICE)); IDSComplianceConfigurationService ccs = IDSComplianceConfigurationService(getDSService(COMPLIANCE_CONFIGURATION_SERVICE)); require(ccs.getNonAccreditedInvestorsLimit() == 0 || (cs.getTotalInvestorsCount() - cs.getAccreditedInvestorsCount() + _totalInvestors - _accreditedInvestors <= ccs.getNonAccreditedInvestorsLimit()), MAX_INVESTORS_IN_CATEGORY); cs.setTotalInvestorsCount(increaseCounter(cs.getTotalInvestorsCount(), ccs.getTotalInvestorsLimit(), _totalInvestors)); cs.setAccreditedInvestorsCount(increaseCounter(cs.getAccreditedInvestorsCount(), ccs.getTotalInvestorsLimit(), _accreditedInvestors)); cs.setUSAccreditedInvestorsCount(increaseCounter(cs.getUSAccreditedInvestorsCount(), ccs.getUSAccreditedInvestorsLimit(), _usAccreditedInvestors)); cs.setUSInvestorsCount(increaseCounter(cs.getUSInvestorsCount(), ccs.getUSInvestorsLimit(), _usTotalInvestors)); cs.setJPInvestorsCount(increaseCounter(cs.getJPInvestorsCount(), ccs.getJPInvestorsLimit(), _jpTotalInvestors)); for (uint i = 0; i < _euRetailCountries.length; i++) { string memory countryCode = bytes32ToString(_euRetailCountries[i]); cs.setEURetailInvestorsCount( countryCode, increaseCounter( cs.getEURetailInvestorsCount(countryCode), ccs.getEURetailInvestorsLimit(), _euRetailCountryCounts[i] ) ); } } return true; } function emitTBEOperationEvent(uint256 _totalInvestors, uint256 _accreditedInvestors, uint256 _usAccreditedInvestors, uint256 _usTotalInvestors, uint256 _jpTotalInvestors, bool /* _increase */) internal { getToken().emitOmnibusTBEEvent( omnibusWallet, int256(_totalInvestors), int256(_accreditedInvestors), int256(_usAccreditedInvestors), int256(_usTotalInvestors), int256(_jpTotalInvestors) ); } function getUintEuCountriesDeltas(int256[] memory euCountryDeltas, bool increase) internal pure returns (uint256[] memory) { uint256[] memory result = new uint256[](euCountryDeltas.length); for (uint i = 0; i < euCountryDeltas.length; i++) { if (increase) { result[i] = euCountryDeltas[i] > 0 ? uint256(euCountryDeltas[i]) : 0; } else { result[i] = euCountryDeltas[i] < 0 ? uint256(euCountryDeltas[i] * -1) : 0; } } return result; } function increaseCounter(uint256 currentValue, uint256 currentLimit, uint256 delta) internal pure returns (uint256) { uint256 result = currentValue + delta; require(currentLimit == 0 || result <= currentLimit, MAX_INVESTORS_IN_CATEGORY); return result; } function bytes32ToString(bytes32 _bytes32) internal pure returns (string memory) { uint8 i = 0; while(i < 32 && _bytes32[i] != 0) { i++; } bytes memory bytesArray = new bytes(i); for (i = 0; i < 32 && _bytes32[i] != 0; i++) { bytesArray[i] = _bytes32[i]; } return string(bytesArray); } }
pragma solidity ^0.8.13; import "../utils/CommonUtils.sol"; import "../utils/VersionedContract.sol"; import "../utils/Initializable.sol"; import "../omnibus/IDSOmnibusWalletController.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSRegistryService is Initializable, VersionedContract { function initialize() public virtual { VERSIONS.push(6); } event DSRegistryServiceInvestorAdded(string investorId, address sender); event DSRegistryServiceInvestorRemoved(string investorId, address sender); event DSRegistryServiceInvestorCountryChanged(string investorId, string country, address sender); event DSRegistryServiceInvestorAttributeChanged(string investorId, uint256 attributeId, uint256 value, uint256 expiry, string proofHash, address sender); event DSRegistryServiceWalletAdded(address wallet, string investorId, address sender); event DSRegistryServiceWalletRemoved(address wallet, string investorId, address sender); event DSRegistryServiceOmnibusWalletAdded(address omnibusWallet, string investorId, IDSOmnibusWalletController omnibusWalletController); event DSRegistryServiceOmnibusWalletRemoved(address omnibusWallet, string investorId); uint8 public constant NONE = 0; uint8 public constant KYC_APPROVED = 1; uint8 public constant ACCREDITED = 2; uint8 public constant QUALIFIED = 4; uint8 public constant PROFESSIONAL = 8; uint8 public constant PENDING = 0; uint8 public constant APPROVED = 1; uint8 public constant REJECTED = 2; uint8 public constant EXCHANGE = 4; modifier investorExists(string memory _id) { require(isInvestor(_id), "Unknown investor"); _; } modifier newInvestor(string memory _id) { require(!CommonUtils.isEmptyString(_id), "Investor id must not be empty"); require(!isInvestor(_id), "Investor already exists"); _; } modifier walletExists(address _address) { require(isWallet(_address), "Unknown wallet"); _; } modifier newWallet(address _address) { require(!isWallet(_address), "Wallet already exists"); _; } modifier newOmnibusWallet(address _omnibusWallet) { require(!isOmnibusWallet(_omnibusWallet), "Omnibus wallet already exists"); _; } modifier omnibusWalletExists(address _omnibusWallet) { require(isOmnibusWallet(_omnibusWallet), "Unknown omnibus wallet"); _; } modifier walletBelongsToInvestor(address _address, string memory _id) { require(CommonUtils.isEqualString(getInvestor(_address), _id), "Wallet does not belong to investor"); _; } function registerInvestor( string memory _id, string memory _collision_hash /*onlyExchangeOrAbove newInvestor(_id)*/ ) public virtual returns (bool); function updateInvestor( string memory _id, string memory _collisionHash, string memory _country, address[] memory _wallets, uint8[] memory _attributeIds, uint256[] memory _attributeValues, uint256[] memory _attributeExpirations /*onlyIssuerOrAbove*/ ) public virtual returns (bool); function removeInvestor( string memory _id /*onlyExchangeOrAbove investorExists(_id)*/ ) public virtual returns (bool); function setCountry( string memory _id, string memory _country /*onlyExchangeOrAbove investorExists(_id)*/ ) public virtual returns (bool); function getCountry(string memory _id) public view virtual returns (string memory); function getCollisionHash(string memory _id) public view virtual returns (string memory); function setAttribute( string memory _id, uint8 _attributeId, uint256 _value, uint256 _expiry, string memory _proofHash /*onlyExchangeOrAbove investorExists(_id)*/ ) public virtual returns (bool); function getAttributeValue(string memory _id, uint8 _attributeId) public view virtual returns (uint256); function getAttributeExpiry(string memory _id, uint8 _attributeId) public view virtual returns (uint256); function getAttributeProofHash(string memory _id, uint8 _attributeId) public view virtual returns (string memory); function addWallet( address _address, string memory _id /*onlyExchangeOrAbove newWallet(_address)*/ ) public virtual returns (bool); function addWalletByInvestor(address _address) public virtual returns (bool); function removeWallet( address _address, string memory _id /*onlyExchangeOrAbove walletExists walletBelongsToInvestor(_address, _id)*/ ) public virtual returns (bool); function addOmnibusWallet( string memory _id, address _omnibusWallet, IDSOmnibusWalletController _omnibusWalletController /*onlyIssuerOrAbove newOmnibusWallet*/ ) public virtual; function removeOmnibusWallet( string memory _id, address _omnibusWallet /*onlyIssuerOrAbove omnibusWalletControllerExists*/ ) public virtual; function getOmnibusWalletController(address _omnibusWallet) public view virtual returns (IDSOmnibusWalletController); function isOmnibusWallet(address _omnibusWallet) public view virtual returns (bool); function getInvestor(address _address) public view virtual returns (string memory); function getInvestorDetails(address _address) public view virtual returns (string memory, string memory); function getInvestorDetailsFull(string memory _id) public view virtual returns (string memory, uint256[] memory, uint256[] memory, string memory, string memory, string memory, string memory); function isInvestor(string memory _id) public view virtual returns (bool); function isWallet(address _address) public view virtual returns (bool); function isAccreditedInvestor(string calldata _id) external view virtual returns (bool); function isQualifiedInvestor(string calldata _id) external view virtual returns (bool); function isAccreditedInvestor(address _wallet) external view virtual returns (bool); function isQualifiedInvestor(address _wallet) external view virtual returns (bool); function getInvestors(address _from, address _to) external view virtual returns (string memory, string memory); }
pragma solidity ^0.8.13; import "../utils/VersionedContract.sol"; import "../utils/Initializable.sol"; import "../omnibus/IDSOmnibusWalletController.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSServiceConsumer is Initializable, VersionedContract { function initialize() public virtual { VERSIONS.push(6); } uint256 public constant TRUST_SERVICE = 1; uint256 public constant DS_TOKEN = 2; uint256 public constant REGISTRY_SERVICE = 4; uint256 public constant COMPLIANCE_SERVICE = 8; uint256 public constant UNUSED_1 = 16; uint256 public constant WALLET_MANAGER = 32; uint256 public constant LOCK_MANAGER = 64; uint256 public constant PARTITIONS_MANAGER = 128; uint256 public constant COMPLIANCE_CONFIGURATION_SERVICE = 256; uint256 public constant TOKEN_ISSUER = 512; uint256 public constant WALLET_REGISTRAR = 1024; uint256 public constant OMNIBUS_TBE_CONTROLLER = 2048; uint256 public constant TRANSACTION_RELAYER = 4096; uint256 public constant TOKEN_REALLOCATOR = 8192; uint256 public constant SECURITIZE_SWAP = 16384; function getDSService(uint256 _serviceId) public view virtual returns (address); function setDSService( uint256 _serviceId, address _address /*onlyMaster*/ ) public virtual returns (bool); event DSServiceSet(uint256 serviceId, address serviceAddress); }
pragma solidity ^0.8.13; import "./IDSServiceConsumer.sol"; import "../data-stores/ServiceConsumerDataStore.sol"; import "../token/IDSToken.sol"; import "../token/IDSTokenPartitioned.sol"; import "../compliance/IDSWalletManager.sol"; import "../compliance/IDSLockManager.sol"; import "../compliance/IDSLockManagerPartitioned.sol"; import "../compliance/IDSComplianceService.sol"; import "../compliance/IDSComplianceServicePartitioned.sol"; import "../compliance/IDSPartitionsManager.sol"; import "../compliance/IDSComplianceConfigurationService.sol"; import "../registry/IDSRegistryService.sol"; import "../omnibus/IDSOmnibusTBEController.sol"; import "../trust/IDSTrustService.sol"; import "../utils/Ownable.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract ServiceConsumer is IDSServiceConsumer, Ownable, ServiceConsumerDataStore { // Bring role constants to save gas both in deployment (less bytecode) and usage uint8 public constant ROLE_NONE = 0; uint8 public constant ROLE_MASTER = 1; uint8 public constant ROLE_ISSUER = 2; uint8 public constant ROLE_EXCHANGE = 4; uint8 public constant ROLE_TRANSFER_AGENT = 8; function initialize() public virtual override(IDSServiceConsumer, Ownable) { IDSServiceConsumer.initialize(); Ownable.initialize(); VERSIONS.push(6); } modifier onlyMaster { IDSTrustService trustManager = getTrustService(); require(this.contractOwner() == msg.sender || trustManager.getRole(msg.sender) == ROLE_MASTER, "Insufficient trust level"); _; } /** * @dev Allow invoking functions only by the users who have the MASTER role or the ISSUER role or the TRANSFER AGENT role. */ modifier onlyIssuerOrTransferAgentOrAbove() { IDSTrustService trustManager = getTrustService(); require(trustManager.getRole(msg.sender) == ROLE_TRANSFER_AGENT || trustManager.getRole(msg.sender) == ROLE_ISSUER || trustManager.getRole(msg.sender) == ROLE_MASTER, "Insufficient trust level"); _; } modifier onlyIssuerOrAbove { IDSTrustService trustManager = getTrustService(); require(trustManager.getRole(msg.sender) == ROLE_ISSUER || trustManager.getRole(msg.sender) == ROLE_MASTER, "Insufficient trust level"); _; } modifier onlyTransferAgentOrAbove { IDSTrustService trustManager = getTrustService(); require(trustManager.getRole(msg.sender) == ROLE_TRANSFER_AGENT || trustManager.getRole(msg.sender) == ROLE_MASTER, "Insufficient trust level"); _; } modifier onlyExchangeOrAbove { IDSTrustService trustManager = getTrustService(); require( trustManager.getRole(msg.sender) == ROLE_EXCHANGE || trustManager.getRole(msg.sender) == ROLE_ISSUER || trustManager.getRole(msg.sender) == ROLE_TRANSFER_AGENT || trustManager.getRole(msg.sender) == ROLE_MASTER, "Insufficient trust level" ); _; } modifier onlyToken { require(msg.sender == getDSService(DS_TOKEN), "This function can only called by the associated token"); _; } modifier onlyRegistry { require(msg.sender == getDSService(REGISTRY_SERVICE), "This function can only called by the registry service"); _; } modifier onlyIssuerOrAboveOrToken { if (msg.sender != getDSService(DS_TOKEN)) { IDSTrustService trustManager = IDSTrustService(getDSService(TRUST_SERVICE)); require(trustManager.getRole(msg.sender) == ROLE_ISSUER || trustManager.getRole(msg.sender) == ROLE_MASTER, "Insufficient trust level"); } _; } modifier onlyTransferAgentOrAboveOrToken { if (msg.sender != getDSService(DS_TOKEN)) { IDSTrustService trustManager = IDSTrustService(getDSService(TRUST_SERVICE)); require(trustManager.getRole(msg.sender) == ROLE_TRANSFER_AGENT || trustManager.getRole(msg.sender) == ROLE_MASTER, "Insufficient trust level"); } _; } modifier onlyOmnibusWalletController(address omnibusWallet, IDSOmnibusWalletController omnibusWalletController) { require(getRegistryService().getOmnibusWalletController(omnibusWallet) == omnibusWalletController, "Wrong controller address"); _; } modifier onlyTBEOmnibus { require(msg.sender == address(getOmnibusTBEController()), "Not authorized"); _; } modifier onlyMasterOrTBEOmnibus { IDSTrustService trustManager = getTrustService(); require(msg.sender == address(getOmnibusTBEController()) || this.contractOwner() == msg.sender || trustManager.getRole(msg.sender) == ROLE_MASTER, "Not authorized"); _; } modifier onlyOwnerOrExchangeOrAbove { if(!isOwner()) { IDSTrustService trustManager = getTrustService(); require( trustManager.getRole(msg.sender) == ROLE_EXCHANGE || trustManager.getRole(msg.sender) == ROLE_ISSUER || trustManager.getRole(msg.sender) == ROLE_TRANSFER_AGENT || trustManager.getRole(msg.sender) == ROLE_MASTER, "Insufficient trust level" ); } _; } function getDSService(uint256 _serviceId) public view override returns (address) { return services[_serviceId]; } function setDSService(uint256 _serviceId, address _address) public override onlyMaster returns (bool) { services[_serviceId] = _address; emit DSServiceSet(_serviceId, _address); return true; } function getToken() internal view returns (IDSToken) { return IDSToken(getDSService(DS_TOKEN)); } function getTrustService() internal view returns (IDSTrustService) { return IDSTrustService(getDSService(TRUST_SERVICE)); } function getWalletManager() internal view returns (IDSWalletManager) { return IDSWalletManager(getDSService(WALLET_MANAGER)); } function getLockManager() internal view returns (IDSLockManager) { return IDSLockManager(getDSService(LOCK_MANAGER)); } function getLockManagerPartitioned() internal view returns (IDSLockManagerPartitioned) { return IDSLockManagerPartitioned(getDSService(LOCK_MANAGER)); } function getComplianceService() internal view returns (IDSComplianceService) { return IDSComplianceService(getDSService(COMPLIANCE_SERVICE)); } function getRegistryService() internal view returns (IDSRegistryService) { return IDSRegistryService(getDSService(REGISTRY_SERVICE)); } function getPartitionsManager() internal view returns (IDSPartitionsManager) { return IDSPartitionsManager(getDSService(PARTITIONS_MANAGER)); } function getTokenPartitioned() internal view returns (IDSTokenPartitioned) { return IDSTokenPartitioned(getDSService(DS_TOKEN)); } function getComplianceConfigurationService() internal view returns (IDSComplianceConfigurationService) { return IDSComplianceConfigurationService(getDSService(COMPLIANCE_CONFIGURATION_SERVICE)); } function getOmnibusTBEController() internal view returns (IDSOmnibusTBEController) { return IDSOmnibusTBEController(getDSService(OMNIBUS_TBE_CONTROLLER)); } }
pragma solidity ^0.8.13; import "../utils/CommonUtils.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../utils/VersionedContract.sol"; import "../utils/Initializable.sol"; import "../omnibus/IDSOmnibusWalletController.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSToken is IERC20, Initializable, VersionedContract { event Issue(address indexed to, uint256 value, uint256 valueLocked); event Burn(address indexed burner, uint256 value, string reason); event Seize(address indexed from, address indexed to, uint256 value, string reason); event OmnibusDeposit(address indexed omnibusWallet, address to, uint256 value, uint8 assetTrackingMode); event OmnibusWithdraw(address indexed omnibusWallet, address from, uint256 value, uint8 assetTrackingMode); event OmnibusSeize(address indexed omnibusWallet, address from, uint256 value, string reason, uint8 assetTrackingMode); event OmnibusBurn(address indexed omnibusWallet, address who, uint256 value, string reason, uint8 assetTrackingMode); event OmnibusTransfer(address indexed omnibusWallet, address from, address to, uint256 value, uint8 assetTrackingMode); event OmnibusTBEOperation(address indexed omnibusWallet, int256 totalDelta, int256 accreditedDelta, int256 usAccreditedDelta, int256 usTotalDelta, int256 jpTotalDelta); event OmnibusTBETransfer(address omnibusWallet, string externalId); event WalletAdded(address wallet); event WalletRemoved(address wallet); function initialize() public virtual { VERSIONS.push(3); } /****************************** CONFIGURATION *******************************/ /** * @dev Sets the total issuance cap * Note: The cap is compared to the total number of issued token, not the total number of tokens available, * So if a token is burned, it is not removed from the "total number of issued". * This call cannot be called again after it was called once. * @param _cap address The address which is going to receive the newly issued tokens */ function setCap( uint256 _cap /*onlyMaster*/ ) public virtual; /****************************** TOKEN ISSUANCE (MINTING) *******************************/ /** * @dev Issues unlocked tokens * @param _to address The address which is going to receive the newly issued tokens * @param _value uint256 the value of tokens to issue * @return true if successful */ function issueTokens( address _to, uint256 _value /*onlyIssuerOrAbove*/ ) public virtual returns (bool); /** * @dev Issuing tokens from the fund * @param _to address The address which is going to receive the newly issued tokens * @param _value uint256 the value of tokens to issue * @param _valueLocked uint256 value of tokens, from those issued, to lock immediately. * @param _reason reason for token locking * @param _releaseTime timestamp to release the lock (or 0 for locks which can only released by an unlockTokens call) * @return true if successful */ function issueTokensCustom( address _to, uint256 _value, uint256 _issuanceTime, uint256 _valueLocked, string memory _reason, uint64 _releaseTime /*onlyIssuerOrAbove*/ ) public virtual returns (bool); function issueTokensWithMultipleLocks( address _to, uint256 _value, uint256 _issuanceTime, uint256[] memory _valuesLocked, string memory _reason, uint64[] memory _releaseTimes /*onlyIssuerOrAbove*/ ) public virtual returns (bool); function issueTokensWithNoCompliance(address _to, uint256 _value) public virtual /*onlyIssuerOrAbove*/; //********************* // TOKEN BURNING //********************* function burn( address _who, uint256 _value, string memory _reason /*onlyIssuerOrAbove*/ ) public virtual; function omnibusBurn( address _omnibusWallet, address _who, uint256 _value, string memory _reason /*onlyIssuerOrAbove*/ ) public virtual; //********************* // TOKEN SIEZING //********************* function seize( address _from, address _to, uint256 _value, string memory _reason /*onlyIssuerOrAbove*/ ) public virtual; function omnibusSeize( address _omnibusWallet, address _from, address _to, uint256 _value, string memory _reason /*onlyIssuerOrAbove*/ ) public virtual; //********************* // WALLET ENUMERATION //********************* function getWalletAt(uint256 _index) public view virtual returns (address); function walletCount() public view virtual returns (uint256); //************************************** // MISCELLANEOUS FUNCTIONS //************************************** function isPaused() public view virtual returns (bool); function balanceOfInvestor(string memory _id) public view virtual returns (uint256); function updateOmnibusInvestorBalance( address _omnibusWallet, address _wallet, uint256 _value, CommonUtils.IncDec _increase /*onlyOmnibusWalletController*/ ) public virtual returns (bool); function emitOmnibusTransferEvent( address _omnibusWallet, address _from, address _to, uint256 _value /*onlyOmnibusWalletController*/ ) public virtual; function emitOmnibusTBEEvent(address omnibusWallet, int256 totalDelta, int256 accreditedDelta, int256 usAccreditedDelta, int256 usTotalDelta, int256 jpTotalDelta /*onlyTBEOmnibus*/ ) public virtual; function emitOmnibusTBETransferEvent(address omnibusWallet, string memory externalId) public virtual; function updateInvestorBalance(address _wallet, uint256 _value, CommonUtils.IncDec _increase) internal virtual returns (bool); function preTransferCheck(address _from, address _to, uint256 _value) public view virtual returns (uint256 code, string memory reason); }
pragma solidity ^0.8.13; import "./IDSToken.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract IDSTokenPartitioned { function balanceOfByPartition(address _who, bytes32 _partition) public view virtual returns (uint256); function balanceOfInvestorByPartition(string memory _id, bytes32 _partition) public view virtual returns (uint256); function partitionCountOf(address _who) public view virtual returns (uint256); function partitionOf(address _who, uint256 _index) public view virtual returns (bytes32); function transferByPartitions(address _to, uint256 _value, bytes32[] memory _partitions, uint256[] memory _values) public virtual returns (bool); function transferFromByPartitions(address _from, address _to, uint256 _value, bytes32[] memory _partitions, uint256[] memory _values) public virtual returns (bool); function burnByPartition( address _who, uint256 _value, string memory _reason, bytes32 _partition /*onlyIssuerOrAbove*/ ) public virtual; function seizeByPartition( address _from, address _to, uint256 _value, string memory _reason, bytes32 _partition /*onlyIssuerOrAbove*/ ) public virtual; event TransferByPartition(address indexed from, address indexed to, uint256 value, bytes32 indexed partition); event IssueByPartition(address indexed to, uint256 value, bytes32 indexed partition); event BurnByPartition(address indexed burner, uint256 value, string reason, bytes32 indexed partition); event SeizeByPartition(address indexed from, address indexed to, uint256 value, string reason, bytes32 indexed partition); }
pragma solidity ^0.8.13; import "../service/ServiceConsumer.sol"; import "../data-stores/TokenDataStore.sol"; import "../omnibus/OmnibusTBEController.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract StandardToken is IDSToken, ServiceConsumer, TokenDataStore { event Pause(); event Unpause(); function initialize() public virtual override(IDSToken, ServiceConsumer) { IDSToken.initialize(); ServiceConsumer.initialize(); VERSIONS.push(5); } modifier whenNotPaused() { require(!paused, "Contract is paused"); _; } modifier whenPaused() { require(paused, "Contract is not paused"); _; } function pause() public onlyTransferAgentOrAbove whenNotPaused { paused = true; emit Pause(); } function unpause() public onlyTransferAgentOrAbove whenPaused { paused = false; emit Unpause(); } function isPaused() public view override returns (bool) { return paused; } /** * @dev Gets the balance of the specified address. * @param _owner The address to query the the balance of. * @return An uint256 representing the amount owned by the passed address. */ function balanceOf(address _owner) public view returns (uint256) { return tokenData.walletsBalances[_owner]; } function totalSupply() public view returns (uint256) { return tokenData.totalSupply; } /** * @dev transfer token for a specified address * @param _to The address to transfer to. * @param _value The amount to be transferred. */ function transfer(address _to, uint256 _value) public virtual returns (bool) { return transferImpl(msg.sender, _to, _value); } function transferFrom( address _from, address _to, uint256 _value ) public virtual returns (bool) { IDSOmnibusTBEController tbeController = getOmnibusTBEController(); if (!(msg.sender == address(tbeController) && _from == tbeController.getOmnibusWallet())) { require(_value <= allowances[_from][msg.sender], "Not enough allowance"); allowances[_from][msg.sender] -= _value; } return transferImpl(_from, _to, _value); } function transferImpl( address _from, address _to, uint256 _value ) internal returns (bool) { require(_to != address(0)); require(_value <= tokenData.walletsBalances[_from]); tokenData.walletsBalances[_from] -= _value; tokenData.walletsBalances[_to] += _value; emit Transfer(_from, _to, _value); return true; } function approve(address _spender, uint256 _value) public returns (bool) { allowances[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; } function allowance(address _owner, address _spender) public view returns (uint256) { return allowances[_owner][_spender]; } function increaseApproval(address _spender, uint256 _addedValue) public returns (bool) { allowances[msg.sender][_spender] = allowances[msg.sender][_spender] + _addedValue; emit Approval(msg.sender, _spender, allowances[msg.sender][_spender]); return true; } function decreaseApproval(address _spender, uint256 _subtractedValue) public returns (bool) { uint256 oldValue = allowances[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowances[msg.sender][_spender] = 0; } else { allowances[msg.sender][_spender] = oldValue - _subtractedValue; } emit Approval(msg.sender, _spender, allowances[msg.sender][_spender]); return true; } }
pragma solidity ^0.8.13; import "../service/ServiceConsumer.sol"; //SPDX-License-Identifier: UNLICENSED library TokenLibrary { event OmnibusDeposit(address indexed omnibusWallet, address to, uint256 value, uint8 assetTrackingMode); event OmnibusWithdraw(address indexed omnibusWallet, address from, uint256 value, uint8 assetTrackingMode); event Issue(address indexed to, uint256 value, uint256 valueLocked); uint256 internal constant COMPLIANCE_SERVICE = 0; uint256 internal constant REGISTRY_SERVICE = 1; uint256 internal constant OMNIBUS_NO_ACTION = 0; uint256 internal constant OMNIBUS_DEPOSIT = 1; uint256 internal constant OMNIBUS_WITHDRAW = 2; using SafeMath for uint256; struct TokenData { mapping(address => uint256) walletsBalances; mapping(string => uint256) investorsBalances; uint256 totalSupply; uint256 totalIssued; } struct SupportedFeatures { uint256 value; } function setFeature(SupportedFeatures storage supportedFeatures, uint8 featureIndex, bool enable) public { uint256 base = 2; uint256 mask = base**featureIndex; // Enable only if the feature is turned off and disable only if the feature is turned on if (enable && (supportedFeatures.value & mask == 0)) { supportedFeatures.value = supportedFeatures.value ^ mask; } else if (!enable && (supportedFeatures.value & mask >= 1)) { supportedFeatures.value = supportedFeatures.value ^ mask; } } function issueTokensCustom( TokenData storage _tokenData, address[] memory _services, IDSLockManager _lockManager, address _to, uint256 _value, uint256 _issuanceTime, uint256[] memory _valuesLocked, uint64[] memory _releaseTimes, string memory _reason, uint256 _cap ) public returns (bool) { //Check input values require(_to != address(0), "Invalid address"); require(_value > 0, "Value is zero"); require(_valuesLocked.length == _releaseTimes.length, "Wrong length of parameters"); //Make sure we are not hitting the cap require(_cap == 0 || _tokenData.totalIssued + _value <= _cap, "Token Cap Hit"); //Check issuance is allowed (and inform the compliance manager, possibly adding locks) IDSComplianceService(_services[COMPLIANCE_SERVICE]).validateIssuance(_to, _value, _issuanceTime); _tokenData.totalSupply += _value; _tokenData.totalIssued += _value; _tokenData.walletsBalances[_to] += _value; updateInvestorBalance(_tokenData, IDSRegistryService(_services[REGISTRY_SERVICE]), _to, _value, CommonUtils.IncDec.Increase); uint256 totalLocked = 0; for (uint256 i = 0; i < _valuesLocked.length; i++) { totalLocked += _valuesLocked[i]; _lockManager.addManualLockRecord(_to, _valuesLocked[i], _reason, _releaseTimes[i]); } require(totalLocked <= _value, "valueLocked must be smaller than value"); emit Issue(_to, _value, totalLocked); return true; } function issueTokensWithNoCompliance( TokenData storage _tokenData, address[] memory _services, address _to, uint256 _value, uint256 _issuanceTime, uint256 _cap ) public returns (bool) { //Make sure we are not hitting the cap require(_cap == 0 || _tokenData.totalIssued + _value <= _cap, "Token Cap Hit"); //Check and inform issuance IDSComplianceService(_services[COMPLIANCE_SERVICE]).validateIssuanceWithNoCompliance(_to, _value, _issuanceTime); _tokenData.totalSupply += _value; _tokenData.totalIssued += _value; _tokenData.walletsBalances[_to] += _value; updateInvestorBalance(_tokenData, IDSRegistryService(_services[REGISTRY_SERVICE]), _to, _value, CommonUtils.IncDec.Increase); emit Issue(_to, _value, 0); return true; } modifier validSeizeParameters(TokenData storage _tokenData, address _from, address _to, uint256 _value) { require(_from != address(0), "Invalid address"); require(_to != address(0), "Invalid address"); require(_value <= _tokenData.walletsBalances[_from], "Not enough balance"); _; } function burn(TokenData storage _tokenData, address[] memory _services, address _who, uint256 _value) public { require(_value <= _tokenData.walletsBalances[_who], "Not enough balance"); // no need to require value <= totalSupply, since that would imply the // sender's balance is greater than the totalSupply, which *should* be an assertion failure IDSComplianceService(_services[COMPLIANCE_SERVICE]).validateBurn(_who, _value); _tokenData.walletsBalances[_who] -= _value; updateInvestorBalance(_tokenData, IDSRegistryService(_services[REGISTRY_SERVICE]), _who, _value, CommonUtils.IncDec.Decrease); _tokenData.totalSupply -= _value; } function seize(TokenData storage _tokenData, address[] memory _services, address _from, address _to, uint256 _value) public validSeizeParameters(_tokenData, _from, _to, _value) { IDSRegistryService registryService = IDSRegistryService(_services[REGISTRY_SERVICE]); IDSComplianceService(_services[COMPLIANCE_SERVICE]).validateSeize(_from, _to, _value); _tokenData.walletsBalances[_from] -= _value; _tokenData.walletsBalances[_to] += _value; updateInvestorBalance(_tokenData, registryService, _from, _value, CommonUtils.IncDec.Decrease); updateInvestorBalance(_tokenData, registryService, _to, _value, CommonUtils.IncDec.Increase); } function omnibusBurn(TokenData storage _tokenData, address[] memory _services, address _omnibusWallet, address _who, uint256 _value) public { IDSRegistryService registryService = IDSRegistryService(_services[REGISTRY_SERVICE]); IDSOmnibusWalletController omnibusController = IDSRegistryService(_services[REGISTRY_SERVICE]).getOmnibusWalletController(_omnibusWallet); _tokenData.walletsBalances[_omnibusWallet] -= _value; omnibusController.burn(_who, _value); decreaseInvestorBalanceOnOmnibusSeizeOrBurn(_tokenData, registryService, omnibusController, _omnibusWallet, _who, _value); _tokenData.totalSupply -= _value; } function omnibusSeize(TokenData storage _tokenData, address[] memory _services, address _omnibusWallet, address _from, address _to, uint256 _value) public validSeizeParameters(_tokenData, _omnibusWallet, _to, _value) { IDSRegistryService registryService = IDSRegistryService(_services[REGISTRY_SERVICE]); IDSOmnibusWalletController omnibusController = registryService.getOmnibusWalletController(_omnibusWallet); _tokenData.walletsBalances[_omnibusWallet] -= _value; _tokenData.walletsBalances[_to] += _value; omnibusController.seize(_from, _value); decreaseInvestorBalanceOnOmnibusSeizeOrBurn(_tokenData, registryService, omnibusController, _omnibusWallet, _from, _value); updateInvestorBalance(_tokenData, registryService, _to, _value, CommonUtils.IncDec.Increase); } function decreaseInvestorBalanceOnOmnibusSeizeOrBurn( TokenData storage _tokenData, IDSRegistryService _registryService, IDSOmnibusWalletController _omnibusController, address _omnibusWallet, address _from, uint256 _value ) internal { if (_omnibusController.isHolderOfRecord()) { updateInvestorBalance(_tokenData, _registryService, _omnibusWallet, _value, CommonUtils.IncDec.Decrease); } else { updateInvestorBalance(_tokenData, _registryService, _from, _value, CommonUtils.IncDec.Decrease); } } function applyOmnibusBalanceUpdatesOnTransfer(TokenData storage _tokenData, IDSRegistryService _registryService, address _from, address _to, uint256 _value) public returns (uint256) { if (_registryService.isOmnibusWallet(_to)) { IDSOmnibusWalletController omnibusWalletController = _registryService.getOmnibusWalletController(_to); omnibusWalletController.deposit(_from, _value); emit OmnibusDeposit(_to, _from, _value, omnibusWalletController.getAssetTrackingMode()); if (omnibusWalletController.isHolderOfRecord()) { updateInvestorBalance(_tokenData, _registryService, _from, _value, CommonUtils.IncDec.Decrease); updateInvestorBalance(_tokenData, _registryService, _to, _value, CommonUtils.IncDec.Increase); } return OMNIBUS_DEPOSIT; } else if (_registryService.isOmnibusWallet(_from)) { IDSOmnibusWalletController omnibusWalletController = _registryService.getOmnibusWalletController(_from); omnibusWalletController.withdraw(_to, _value); emit OmnibusWithdraw(_from, _to, _value, omnibusWalletController.getAssetTrackingMode()); if (omnibusWalletController.isHolderOfRecord()) { updateInvestorBalance(_tokenData, _registryService, _from, _value, CommonUtils.IncDec.Decrease); updateInvestorBalance(_tokenData, _registryService, _to, _value, CommonUtils.IncDec.Increase); } return OMNIBUS_WITHDRAW; } return OMNIBUS_NO_ACTION; } function updateInvestorBalance(TokenData storage _tokenData, IDSRegistryService _registryService, address _wallet, uint256 _value, CommonUtils.IncDec _increase) internal returns (bool) { string memory investor = _registryService.getInvestor(_wallet); if (!CommonUtils.isEmptyString(investor)) { uint256 balance = _tokenData.investorsBalances[investor]; if (_increase == CommonUtils.IncDec.Increase) { balance += _value; } else { balance -= _value; } _tokenData.investorsBalances[investor] = balance; } return true; } }
pragma solidity ^0.8.13; import "../utils/CommonUtils.sol"; import "../compliance/IDSComplianceServicePartitioned.sol"; import "../compliance/IDSLockManagerPartitioned.sol"; import "../registry/IDSRegistryService.sol"; import "../compliance/IDSComplianceConfigurationService.sol"; import "../compliance/IDSPartitionsManager.sol"; import "../omnibus/IDSOmnibusTBEController.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; //SPDX-License-Identifier: UNLICENSED library TokenPartitionsLibrary { using SafeMath for uint256; uint256 internal constant COMPLIANCE_SERVICE = 0; uint256 internal constant REGISTRY_SERVICE = 1; uint256 internal constant OMNIBUS_TBE_CONTROLLER = 2; event IssueByPartition(address indexed to, uint256 value, bytes32 indexed partition); event TransferByPartition(address indexed from, address indexed to, uint256 value, bytes32 indexed partition); struct AddressPartitions { uint256 count; mapping(bytes32 => uint256) toIndex; mapping(uint256 => bytes32) partitions; mapping(bytes32 => uint256) balances; } struct TokenPartitions { mapping(address => AddressPartitions) walletPartitions; mapping(string => mapping(bytes32 => uint256)) investorPartitionsBalances; } function issueTokensCustom( TokenPartitions storage self, IDSRegistryService _registry, IDSComplianceConfigurationService _compConf, IDSPartitionsManager _partitionsManager, IDSLockManagerPartitioned _lockManager, address _to, uint256 _value, uint256 _issuanceTime, uint256[] memory _valuesLocked, string memory _reason, uint64[] memory _releaseTimes ) public returns (bool) { string memory investor = _registry.getInvestor(_to); string memory country = _registry.getCountry(investor); bytes32 partition = _partitionsManager.ensurePartition(_issuanceTime, _compConf.getCountryCompliance(country)); emit IssueByPartition(_to, _value, partition); transferPartition(self, _registry, address(0), _to, _value, partition); uint256 totalLocked = 0; for (uint256 i = 0; i < _valuesLocked.length; i++) { totalLocked += _valuesLocked[i]; _lockManager.createLockForInvestor(investor, _valuesLocked[i], 0, _reason, _releaseTimes[i], partition); } require(totalLocked <= _value, "valueLocked must be smaller than value"); return true; } function issueTokensWithNoCompliance( TokenPartitions storage self, IDSRegistryService _registry, IDSComplianceConfigurationService _compConf, IDSPartitionsManager _partitionsManager, address _to, uint256 _value, uint256 _issuanceTime ) public returns (bool) { string memory investor = _registry.getInvestor(_to); string memory country = _registry.getCountry(investor); bytes32 partition = _partitionsManager.ensurePartition(_issuanceTime, _compConf.getCountryCompliance(country)); emit IssueByPartition(_to, _value, partition); transferPartition(self, _registry, address(0), _to, _value, partition); return true; } function setPartitionToAddressImpl(TokenPartitions storage self, address _who, uint256 _index, bytes32 _partition) internal returns (bool) { self.walletPartitions[_who].partitions[_index] = _partition; self.walletPartitions[_who].toIndex[_partition] = _index; return true; } function addPartitionToAddress(TokenPartitions storage self, address _who, bytes32 _partition) internal { uint256 partitionCount = self.walletPartitions[_who].count; setPartitionToAddressImpl(self, _who, self.walletPartitions[_who].count, _partition); self.walletPartitions[_who].count = SafeMath.add(partitionCount, 1); } function removePartitionFromAddress(TokenPartitions storage self, address _from, bytes32 _partition) internal { uint256 oldIndex = self.walletPartitions[_from].toIndex[_partition]; uint256 lastPartitionIndex = SafeMath.sub(self.walletPartitions[_from].count, 1); bytes32 lastPartition = self.walletPartitions[_from].partitions[lastPartitionIndex]; setPartitionToAddressImpl(self, _from, oldIndex, lastPartition); delete self.walletPartitions[_from].partitions[lastPartitionIndex]; delete self.walletPartitions[_from].toIndex[_partition]; delete self.walletPartitions[_from].balances[_partition]; self.walletPartitions[_from].count = SafeMath.sub(self.walletPartitions[_from].count, 1); } function transferPartition(TokenPartitions storage self, IDSRegistryService _registry, address _from, address _to, uint256 _value, bytes32 _partition) public { if (_from != address(0)) { self.walletPartitions[_from].balances[_partition] = SafeMath.sub(self.walletPartitions[_from].balances[_partition], _value); updateInvestorPartitionBalance(self, _registry, _from, _value, CommonUtils.IncDec.Decrease, _partition); if (self.walletPartitions[_from].balances[_partition] == 0) { removePartitionFromAddress(self, _from, _partition); } } if (_to != address(0)) { if (self.walletPartitions[_to].balances[_partition] == 0 && _value > 0) { addPartitionToAddress(self, _to, _partition); } self.walletPartitions[_to].balances[_partition] += _value; updateInvestorPartitionBalance(self, _registry, _to, _value, CommonUtils.IncDec.Increase, _partition); } emit TransferByPartition(_from, _to, _value, _partition); } function transferPartitions(TokenPartitions storage self, address[] memory _services, address _from, address _to, uint256 _value) public returns (bool) { uint256 partitionCount = partitionCountOf(self, _from); uint256 index = 0; bool skipComplianceCheck = shouldSkipComplianceCheck(IDSRegistryService(_services[REGISTRY_SERVICE]), IDSOmnibusTBEController(_services[OMNIBUS_TBE_CONTROLLER]), _from, _to); while (_value > 0 && index < partitionCount) { bytes32 partition = partitionOf(self, _from, index); uint256 transferableInPartition = skipComplianceCheck ? self.walletPartitions[_from].balances[partition] : IDSComplianceServicePartitioned(_services[COMPLIANCE_SERVICE]).getComplianceTransferableTokens(_from, block.timestamp, _to, partition); uint256 transferable = Math.min(_value, transferableInPartition); if (transferable > 0) { if (self.walletPartitions[_from].balances[partition] == transferable) { unchecked { --index; --partitionCount; } } transferPartition(self, IDSRegistryService(_services[REGISTRY_SERVICE]), _from, _to, transferable, partition); _value -= transferable; } unchecked { ++index; } } require(_value == 0); return true; } function transferPartitions( TokenPartitions storage self, address[] memory _services, address _from, address _to, uint256 _value, bytes32[] memory _partitions, uint256[] memory _values ) public returns (bool) { require(_partitions.length == _values.length); bool skipComplianceCheck = shouldSkipComplianceCheck(IDSRegistryService(_services[REGISTRY_SERVICE]), IDSOmnibusTBEController(_services[OMNIBUS_TBE_CONTROLLER]), _from, _to); for (uint256 index = 0; index < _partitions.length; ++index) { if (!skipComplianceCheck) { require(_values[index] <= IDSComplianceServicePartitioned(_services[COMPLIANCE_SERVICE]).getComplianceTransferableTokens(_from, block.timestamp, _to, _partitions[index])); } transferPartition(self, IDSRegistryService(_services[REGISTRY_SERVICE]), _from, _to, _values[index], _partitions[index]); _value -= _values[index]; } require(_value == 0); return true; } function balanceOfByPartition(TokenPartitions storage self, address _who, bytes32 _partition) internal view returns (uint256) { return self.walletPartitions[_who].balances[_partition]; } function balanceOfInvestorByPartition(TokenPartitions storage self, string memory _id, bytes32 _partition) internal view returns (uint256) { return self.investorPartitionsBalances[_id][_partition]; } function partitionCountOf(TokenPartitions storage self, address _who) internal view returns (uint256) { return self.walletPartitions[_who].count; } function partitionOf(TokenPartitions storage self, address _who, uint256 _index) internal view returns (bytes32) { return self.walletPartitions[_who].partitions[_index]; } function updateInvestorPartitionBalance(TokenPartitions storage self, IDSRegistryService _registry, address _wallet, uint256 _value, CommonUtils.IncDec _increase, bytes32 _partition) internal returns (bool) { string memory investor = _registry.getInvestor(_wallet); if (!CommonUtils.isEmptyString(investor)) { uint256 balance = self.investorPartitionsBalances[investor][_partition]; if (_increase == CommonUtils.IncDec.Increase) { balance = SafeMath.add(balance, _value); } else { balance = SafeMath.sub(balance, _value); } self.investorPartitionsBalances[investor][_partition] = balance; } return true; } function shouldSkipComplianceCheck(IDSRegistryService _registry, IDSOmnibusTBEController _omnibusTBEController, address _from, address _to) internal view returns (bool) { return CommonUtils.isEqualString(_registry.getInvestor(_from), _registry.getInvestor(_to)) || (address(_omnibusTBEController) != address(0) && (_omnibusTBEController.getOmnibusWallet() == _from || _omnibusTBEController.getOmnibusWallet() == _to)); } }
pragma solidity ^0.8.13; import "../utils/VersionedContract.sol"; import "../utils/Initializable.sol"; /** * @title IDSTrustService * @dev An interface for a trust service which allows role-based access control for other contracts. */ //SPDX-License-Identifier: UNLICENSED abstract contract IDSTrustService is Initializable, VersionedContract { function initialize() public virtual { VERSIONS.push(4); } /** * @dev Should be emitted when a role is set for a user. */ event DSTrustServiceRoleAdded(address targetAddress, uint8 role, address sender); /** * @dev Should be emitted when a role is removed for a user. */ event DSTrustServiceRoleRemoved(address targetAddress, uint8 role, address sender); // Role constants uint8 public constant NONE = 0; uint8 public constant MASTER = 1; uint8 public constant ISSUER = 2; uint8 public constant EXCHANGE = 4; uint8 public constant TRANSFER_AGENT = 8; /** * @dev Transfers the ownership (MASTER role) of the contract. * @param _address The address which the ownership needs to be transferred to. * @return A boolean that indicates if the operation was successful. */ function setServiceOwner( address _address /*onlyMaster*/ ) public virtual returns (bool); /** * @dev Sets a role for an array of wallets. * @dev Should not be used for setting MASTER (use setServiceOwner) or role removal (use removeRole). * @param _addresses The array of wallet whose role needs to be set. * @param _roles The array of role to be set. The lenght and order must match with _addresses * @return A boolean that indicates if the operation was successful. */ function setRoles(address[] memory _addresses, uint8[] memory _roles) public virtual returns (bool); /** * @dev Sets a role for a wallet. * @dev Should not be used for setting MASTER (use setServiceOwner) or role removal (use removeRole). * @param _address The wallet whose role needs to be set. * @param _role The role to be set. * @return A boolean that indicates if the operation was successful. */ function setRole( address _address, uint8 _role /*onlyMasterOrIssuer*/ ) public virtual returns (bool); /** * @dev Removes the role for a wallet. * @dev Should not be used to remove MASTER (use setServiceOwner). * @param _address The wallet whose role needs to be removed. * @return A boolean that indicates if the operation was successful. */ function removeRole( address _address /*onlyMasterOrIssuer*/ ) public virtual returns (bool); /** * @dev Gets the role for a wallet. * @param _address The wallet whose role needs to be fetched. * @return A boolean that indicates if the operation was successful. */ function getRole(address _address) public view virtual returns (uint8); function addEntity( string memory _name, address _owner /*onlyMasterOrIssuer onlyNewEntity onlyNewEntityOwner*/ ) public virtual; function changeEntityOwner( string memory _name, address _oldOwner, address _newOwner /*onlyMasterOrIssuer onlyExistingEntityOwner*/ ) public virtual; function addOperator( string memory _name, address _operator /*onlyEntityOwnerOrAbove onlyNewOperator*/ ) public virtual; function removeOperator( string memory _name, address _operator /*onlyEntityOwnerOrAbove onlyExistingOperator*/ ) public virtual; function addResource( string memory _name, address _resource /*onlyMasterOrIssuer onlyExistingEntity onlyNewResource*/ ) public virtual; function removeResource( string memory _name, address _resource /*onlyMasterOrIssuer onlyExistingResource*/ ) public virtual; function getEntityByOwner(address _owner) public view virtual returns (string memory); function getEntityByOperator(address _operator) public view virtual returns (string memory); function getEntityByResource(address _resource) public view virtual returns (string memory); function isResourceOwner(address _resource, address _owner) public view virtual returns (bool); function isResourceOperator(address _resource, address _operator) public view virtual returns (bool); }
pragma solidity ^0.8.13; //SPDX-License-Identifier: UNLICENSED library CommonUtils { enum IncDec { Increase, Decrease } function encodeString(string memory _str) internal pure returns (bytes32) { return keccak256(abi.encodePacked(_str)); } function isEqualString(string memory _str1, string memory _str2) internal pure returns (bool) { return encodeString(_str1) == encodeString(_str2); } function isEmptyString(string memory _str) internal pure returns (bool) { return isEqualString(_str, ""); } }
pragma solidity ^0.8.13; //SPDX-License-Identifier: UNLICENSED contract Initializable { bool public initialized = false; modifier initializer() { require(!initialized, "Contract instance has already been initialized"); _; initialized = true; } }
pragma solidity ^0.8.13; import "./Initializable.sol"; //SPDX-License-Identifier: UNLICENSED abstract contract Ownable is Initializable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function initialize() public virtual initializer { _owner = msg.sender; emit OwnershipTransferred(address(0), _owner); } //Legacy function function owner() public view returns (address) { return contractOwner(); } function contractOwner() public view returns (address) { return _owner; } modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } function isOwner() public view returns (bool) { return msg.sender == _owner; } function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
pragma solidity ^0.8.13; //SPDX-License-Identifier: UNLICENSED contract ProxyTarget { address internal ___t1; address internal ___t2; modifier forceInitializeFromProxy() { require(___t1 != address(0x0), "Must be initialized from proxy"); _; } }
pragma solidity ^0.8.13; //SPDX-License-Identifier: UNLICENSED contract VersionedContract { uint256[] internal VERSIONS = [1]; function getVersion() public view returns (uint256[] memory) { return VERSIONS; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "contracts/token/TokenLibrary.sol": { "TokenLibrary": "0xebc72c3a7a8e5c615f200a12528d32b3c5c69ea8" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"burner","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"serviceId","type":"uint256"},{"indexed":false,"internalType":"address","name":"serviceAddress","type":"address"}],"name":"DSServiceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"valueLocked","type":"uint256"}],"name":"Issue","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"omnibusWallet","type":"address"},{"indexed":false,"internalType":"address","name":"who","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"},{"indexed":false,"internalType":"uint8","name":"assetTrackingMode","type":"uint8"}],"name":"OmnibusBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"omnibusWallet","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"assetTrackingMode","type":"uint8"}],"name":"OmnibusDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"omnibusWallet","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"},{"indexed":false,"internalType":"uint8","name":"assetTrackingMode","type":"uint8"}],"name":"OmnibusSeize","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"omnibusWallet","type":"address"},{"indexed":false,"internalType":"int256","name":"totalDelta","type":"int256"},{"indexed":false,"internalType":"int256","name":"accreditedDelta","type":"int256"},{"indexed":false,"internalType":"int256","name":"usAccreditedDelta","type":"int256"},{"indexed":false,"internalType":"int256","name":"usTotalDelta","type":"int256"},{"indexed":false,"internalType":"int256","name":"jpTotalDelta","type":"int256"}],"name":"OmnibusTBEOperation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"omnibusWallet","type":"address"},{"indexed":false,"internalType":"string","name":"externalId","type":"string"}],"name":"OmnibusTBETransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"omnibusWallet","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"assetTrackingMode","type":"uint8"}],"name":"OmnibusTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"omnibusWallet","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"assetTrackingMode","type":"uint8"}],"name":"OmnibusWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"Seize","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wallet","type":"address"}],"name":"WalletAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wallet","type":"address"}],"name":"WalletRemoved","type":"event"},{"inputs":[],"name":"COMPLIANCE_CONFIGURATION_SERVICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COMPLIANCE_SERVICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DS_TOKEN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCK_MANAGER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OMNIBUS_TBE_CONTROLLER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PARTITIONS_MANAGER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REGISTRY_SERVICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_EXCHANGE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_ISSUER","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_MASTER","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_NONE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_TRANSFER_AGENT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECURITIZE_SWAP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_ISSUER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_REALLOCATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRANSACTION_RELAYER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRUST_SERVICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNUSED_1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WALLET_MANAGER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WALLET_REGISTRAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_id","type":"string"}],"name":"balanceOfInvestor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_who","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"string","name":"_reason","type":"string"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"omnibusWallet","type":"address"},{"internalType":"int256","name":"totalDelta","type":"int256"},{"internalType":"int256","name":"accreditedDelta","type":"int256"},{"internalType":"int256","name":"usAccreditedDelta","type":"int256"},{"internalType":"int256","name":"usTotalDelta","type":"int256"},{"internalType":"int256","name":"jpTotalDelta","type":"int256"}],"name":"emitOmnibusTBEEvent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"omnibusWallet","type":"address"},{"internalType":"string","name":"externalId","type":"string"}],"name":"emitOmnibusTBETransferEvent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_omnibusWallet","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"emitOmnibusTransferEvent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_serviceId","type":"uint256"}],"name":"getDSService","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVersion","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getWalletAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"issueTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_issuanceTime","type":"uint256"},{"internalType":"uint256","name":"_valueLocked","type":"uint256"},{"internalType":"string","name":"_reason","type":"string"},{"internalType":"uint64","name":"_releaseTime","type":"uint64"}],"name":"issueTokensCustom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_issuanceTime","type":"uint256"},{"internalType":"uint256[]","name":"_valuesLocked","type":"uint256[]"},{"internalType":"string","name":"_reason","type":"string"},{"internalType":"uint64[]","name":"_releaseTimes","type":"uint64[]"}],"name":"issueTokensWithMultipleLocks","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"issueTokensWithNoCompliance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_omnibusWallet","type":"address"},{"internalType":"address","name":"_who","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"string","name":"_reason","type":"string"}],"name":"omnibusBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_omnibusWallet","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"string","name":"_reason","type":"string"}],"name":"omnibusSeize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"preTransferCheck","outputs":[{"internalType":"uint256","name":"code","type":"uint256"},{"internalType":"string","name":"reason","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"string","name":"_reason","type":"string"}],"name":"seize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cap","type":"uint256"}],"name":"setCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_serviceId","type":"uint256"},{"internalType":"address","name":"_address","type":"address"}],"name":"setDSService","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"featureIndex","type":"uint8"},{"internalType":"bool","name":"enable","type":"bool"}],"name":"setFeature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"features","type":"uint256"}],"name":"setFeatures","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supportedFeatures","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalIssued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_omnibusWallet","type":"address"},{"internalType":"address","name":"_wallet","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"enum CommonUtils.IncDec","name":"_increase","type":"uint8"}],"name":"updateOmnibusInvestorBalance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"walletCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6001805460ff60a01b1916815560a060405260808181526200002591600291906200003a565b503480156200003357600080fd5b50620000a6565b8280548282559060005260206000209081019282156200007d579160200282015b828111156200007d578251829060ff169055916020019190600101906200005b565b506200008b9291506200008f565b5090565b5b808211156200008b576000815560010162000090565b61435480620000b66000396000f3fe608060405234801561001057600080fd5b50600436106103f15760003560e01c8063712d5fa211610215578063ae22901d11610125578063ce606ee0116100b8578063dd62ed3e11610087578063dd62ed3e146107b8578063f11d785c146107f1578063f2fde38b14610804578063f5be319314610817578063fbb24bf41461081f57600080fd5b8063ce606ee014610784578063d3f61d7014610795578063d73dd6231461079d578063d8486d29146107b057600080fd5b8063b9683af0116100f4578063b9683af01461074d578063c4b8c5a014610760578063c754015014610768578063cc1bbe491461077157600080fd5b8063ae22901d14610729578063b187bd2614610732578063b696bf021461073d578063b8632a041461074557600080fd5b8063897c002e116101a857806395d89b411161017757806395d89b41146106ea5780639aa25f25146106f25780639c37b8e114610705578063a9059cbb1461070d578063add377391461072057600080fd5b8063897c002e146106b45780638da5cb5b146106bc5780638f32d59b146106c457806393af4a47146106d757600080fd5b8063794d3850116101e4578063794d3850146106945780637f4072351461069c5780638129fc1c146106a45780638456cb59146106ac57600080fd5b8063712d5fa214610667578063715018a61461067a5780637627f6c41461068257806377cc16e01461068c57600080fd5b806329b57c691161031057806340801b6c116102a35780634c83c126116102725780634c83c126146105fc57806359fefa471461060557806366188463146106185780636f2968981461062b57806370a082311461063e57600080fd5b806340801b6c146105c6578063475a9fa9146105ce57806347786d37146105e157806349ce2a16146105f457600080fd5b80633ce5aae9116102df5780633ce5aae91461059a5780633f4ba83a146105ad5780633f727f24146105b55780634021d0a2146105be57600080fd5b806329b57c6914610557578063313ce5671461055f578063355274ea1461057e578063356c52b01461058757600080fd5b8063158ef93e1161038857806318160ddd1161035757806318160ddd146105085780631f227b431461051057806323b872dd1461053157806324ffea9a1461054457600080fd5b8063158ef93e146104c557806315f570dc146104d95780631624f6c6146104ec5780631722957f146104ff57600080fd5b8063095ea7b3116103c4578063095ea7b3146104755780630bffae76146104885780630d8e6e2c1461049d5780630e5324be146104b257600080fd5b8063023f8fd1146103f657806306fdde031461042657806307a8db0a1461043b578063082af7c014610452575b600080fd5b61040961040436600461358a565b610832565b6040516001600160a01b0390911681526020015b60405180910390f35b61042e61086a565b60405161041d91906135fb565b61044461400081565b60405190815260200161041d565b610465610460366004613623565b6108f8565b604051901515815260200161041d565b610465610483366004613653565b610a82565b61049b61049636600461367f565b610aee565b005b6104a5610c27565b60405161041d91906136d0565b6104096104c036600461358a565b610c7f565b60015461046590600160a01b900460ff1681565b61049b6104e73660046137d7565b610c9a565b61049b6104fa36600461383e565b610f16565b61044461080081565b600754610444565b61052361051e3660046138b5565b611019565b60405161041d9291906138f6565b61046561053f3660046138b5565b6110b0565b6104656105523660046139c3565b6111a6565b600b54610444565b60125461056c9060ff1681565b60405160ff909116815260200161041d565b610444600f5481565b61049b61059536600461358a565b611399565b61049b6105a8366004613ac6565b6114b3565b61049b6116d1565b61044461200081565b610444600281565b61056c600181565b6104656105dc366004613653565b611860565b61049b6105ef36600461358a565b61188b565b610444608081565b61044461040081565b61049b610613366004613b3f565b6119f4565b610465610626366004613653565b611b81565b610444610639366004613b6d565b611c6a565b61044461064c366004613ba1565b6001600160a01b031660009081526005602052604090205490565b610465610675366004613bbe565b611c95565b61049b611d53565b6013546104449081565b61056c600081565b61056c600281565b610444604081565b61049b611df7565b61049b611e50565b610444600481565b610409611fdf565b6003546001600160a01b03163314610465565b61049b6106e5366004613653565b611ff8565b61042e612278565b610465610700366004613c39565b612285565b610444602081565b61046561071b366004613653565b61235a565b61044461020081565b61044461100081565b60145460ff16610465565b610444600181565b610444600881565b61049b61075b366004613ac6565b61244e565b610444601081565b61044461010081565b61049b61077f366004613c90565b6126c4565b6003546001600160a01b0316610409565b61056c600481565b6104656107ab366004613653565b61275a565b61056c600881565b6104446107c6366004613cdf565b6001600160a01b03918216600090815260096020908152604080832093909416825291909152205490565b61049b6107ff366004613d0d565b6127e0565b61049b610812366004613ba1565b612890565b600854610444565b61049b61082d366004613d59565b6128f6565b600080821180156108455750600b548211155b61084e57600080fd5b506000908152600a60205260409020546001600160a01b031690565b6010805461087790613dd7565b80601f01602080910402602001604051908101604052809291908181526020018280546108a390613dd7565b80156108f05780601f106108c5576101008083540402835291602001916108f0565b820191906000526020600020905b8154815290600101906020018083116108d357829003601f168201915b505050505081565b600080610903612b66565b9050336001600160a01b0316306001600160a01b031663ce606ee06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561094d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109719190613e11565b6001600160a01b031614806109f15750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa1580156109c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ec9190613e2e565b60ff16145b610a165760405162461bcd60e51b8152600401610a0d90613e4b565b60405180910390fd5b60008481526004602090815260409182902080546001600160a01b0319166001600160a01b0387169081179091558251878152918201527f8a9dba1dc2a1daab74cedc87602df39dcebeacc96d1f5bf104159897a96bebaf910160405180910390a15060019392505050565b3360008181526009602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610add9086815260200190565b60405180910390a350600192915050565b833380610af9612b72565b60405163abfa456f60e01b81526001600160a01b038581166004830152919091169063abfa456f90602401602060405180830381865afa158015610b41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b659190613e11565b6001600160a01b031614610bb65760405162461bcd60e51b815260206004820152601860248201527757726f6e6720636f6e74726f6c6c6572206164647265737360401b6044820152606401610a0d565b856001600160a01b03167fa9ef15dd6e8530645f6476ab6ac36f1cb5acefe0eef5bf5c04664bb251ea01db868686610bed8b612b7e565b604080516001600160a01b0395861681529490931660208501529183015260ff1660608201526080015b60405180910390a2505050505050565b60606002805480602002602001604051908101604052809291908181526020018280548015610c7557602002820191906000526020600020905b815481526020019060010190808311610c61575b5050505050905090565b6000908152600460205260409020546001600160a01b031690565b6000610ca4612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa158015610cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d129190613e2e565b60ff161480610d8c5750604051634427673360e01b81523360048201526002906001600160a01b03831690634427673390602401602060405180830381865afa158015610d63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d879190613e2e565b60ff16145b80610e025750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015610dd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfd9190613e2e565b60ff16145b610e1e5760405162461bcd60e51b8152600401610a0d90613e4b565b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea8638948a4696005610e42612c5b565b87876040518563ffffffff1660e01b8152600401610e639493929190613ec6565b60006040518083038186803b158015610e7b57600080fd5b505af4158015610e8f573d6000803e3d6000fd5b50505050836001600160a01b03167f47e772fda56eb54ab211642ce5421882c49fc2b7033455982af14588ae4207ff8484604051610ece9291906138f6565b60405180910390a26040518381526000906001600160a01b038616906000805160206142ff8339815191529060200160405180910390a3610f10846000612d36565b50505050565b600154600160a01b900460ff1615610f405760405162461bcd60e51b8152600401610a0d90613efb565b6000546001600160a01b0316610f985760405162461bcd60e51b815260206004820152601e60248201527f4d75737420626520696e697469616c697a65642066726f6d2070726f787900006044820152606401610a0d565b610fa0611df7565b6002805460018101825560009190915260056000805160206142df833981519152909101558251610fd89060109060208601906134f1565b508151610fec9060119060208501906134f1565b506012805460ff90921660ff1990921691909117905550506001805460ff60a01b1916600160a01b179055565b60006060611025612d8a565b604051631f227b4360e01b81526001600160a01b0387811660048301528681166024830152604482018690529190911690631f227b4390606401600060405180830381865afa15801561107c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110a49190810190613f8e565b91509150935093915050565b60008383836110bd612d8a565b6001600160a01b031663d794eb76848484601460009054906101000a900460ff166110fd896001600160a01b031660009081526005602052604090205490565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152604484019190915215156064830152608482015260a4016020604051808303816000875af1158015611160573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111849190613fca565b5061119b611193888888612d96565b888888612ee8565b979650505050505050565b6000806111b1612b66565b604051634427673360e01b81523360048201529091506002906001600160a01b03831690634427673390602401602060405180830381865afa1580156111fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121f9190613e2e565b60ff1614806112995750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015611270573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112949190613e2e565b60ff16145b6112b55760405162461bcd60e51b8152600401610a0d90613e4b565b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea86385e9c5bf60056112d9612c5b565b6112e1612f0e565b8c8c8c8c8b8d600f546040518b63ffffffff1660e01b815260040161130f9a99989796959493929190614020565b602060405180830381865af415801561132c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113509190613fca565b506040518781526001600160a01b038916906000906000805160206142ff8339815191529060200160405180910390a361138b600089612d36565b506001979650505050505050565b60006113a3612b66565b9050336001600160a01b0316306001600160a01b031663ce606ee06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114119190613e11565b6001600160a01b031614806114915750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015611468573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148c9190613e2e565b60ff16145b6114ad5760405162461bcd60e51b8152600401610a0d90613e4b565b50601355565b60006114bd612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa158015611507573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152b9190613e2e565b60ff1614806115a55750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa15801561157c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a09190613e2e565b60ff16145b6115c15760405162461bcd60e51b8152600401610a0d90613e4b565b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea8638d876d3860056115e5612c5b565b8888886040518663ffffffff1660e01b81526004016116089594939291906140d9565b60006040518083038186803b15801561162057600080fd5b505af4158015611634573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b03167f5068c48f7f290ce2b8d555bd28014be9f312999bb621037ea3e9fc86335a21d7858560405161167d9291906138f6565b60405180910390a3836001600160a01b0316856001600160a01b03166000805160206142ff833981519152856040516116b891815260200190565b60405180910390a36116ca8585612d36565b5050505050565b60006116db612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa158015611725573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117499190613e2e565b60ff1614806117c35750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa15801561179a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117be9190613e2e565b60ff16145b6117df5760405162461bcd60e51b8152600401610a0d90613e4b565b60145460ff1661182a5760405162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9858dd081a5cc81b9bdd081c185d5cd95960521b6044820152606401610a0d565b6014805460ff191690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a150565b60006118818383426000604051806020016040528060008152506000611c95565b5060019392505050565b6000611895612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa1580156118df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119039190613e2e565b60ff16148061197d5750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015611954573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119789190613e2e565b60ff16145b6119995760405162461bcd60e51b8152600401610a0d90613e4b565b600f54156119e15760405162461bcd60e51b8152602060048201526015602482015274151bdad95b8818d85c08185b1c9958591e481cd95d605a1b6044820152606401610a0d565b600082116119ee57600080fd5b50600f55565b60006119fe612b66565b9050336001600160a01b0316306001600160a01b031663ce606ee06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6c9190613e11565b6001600160a01b03161480611aec5750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015611ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae79190613e2e565b60ff16145b611b085760405162461bcd60e51b8152600401610a0d90613e4b565b604051635eafc2b960e11b81526013600482015260ff84166024820152821515604482015273ebc72c3a7a8e5c615f200a12528d32b3c5c69ea89063bd5f85729060640160006040518083038186803b158015611b6457600080fd5b505af4158015611b78573d6000803e3d6000fd5b50505050505050565b3360009081526009602090815260408083206001600160a01b038616845290915281205480831115611bd6573360009081526009602090815260408083206001600160a01b0388168452909152812055611c05565b611be0838261412c565b3360009081526009602090815260408083206001600160a01b03891684529091529020555b3360008181526009602090815260408083206001600160a01b038916808552908352928190205490519081529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a35060019392505050565b6000600560010182604051611c7f9190614143565b9081526020016040518091039020549050919050565b60006060808515611d3557604080516001808252818301909252906020808301908036833750506040805160018082528183019092529294509050602080830190803683370190505090508582600081518110611cf457611cf461415f565b6020026020010181815250508381600081518110611d1457611d1461415f565b60200260200101906001600160401b031690816001600160401b0316815250505b611d438989898589866111a6565b5060019998505050505050505050565b6003546001600160a01b03163314611dad5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a0d565b6003546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600380546001600160a01b0319169055565b611e216002805460018101825560009190915260036000805160206142df83398151915290910155565b611e29612f1a565b6002805460018101825560009190915260056000805160206142df83398151915290910155565b6000611e5a612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa158015611ea4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec89190613e2e565b60ff161480611f425750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015611f19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3d9190613e2e565b60ff16145b611f5e5760405162461bcd60e51b8152600401610a0d90613e4b565b60145460ff1615611fa65760405162461bcd60e51b815260206004820152601260248201527110dbdb9d1c9858dd081a5cc81c185d5cd95960721b6044820152606401610a0d565b6014805460ff191660011790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a150565b6000611ff36003546001600160a01b031690565b905090565b6000612002612b66565b604051634427673360e01b81523360048201529091506002906001600160a01b03831690634427673390602401602060405180830381865afa15801561204c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120709190613e2e565b60ff1614806120ea5750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa1580156120c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e59190613e2e565b60ff16145b6121065760405162461bcd60e51b8152600401610a0d90613e4b565b61210e612b72565b6040516333955c3b60e21b81526001600160a01b038581166004830152919091169063ce5570ec90602401602060405180830381865afa158015612156573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217a9190613fca565b6121b75760405162461bcd60e51b815260206004820152600e60248201526d155b9adb9bdddb881dd85b1b195d60921b6044820152606401610a0d565b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea863678661c860056121db612c5b565b868642600f546040518763ffffffff1660e01b815260040161220296959493929190614175565b602060405180830381865af415801561221f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122439190613fca565b506040518281526001600160a01b038416906000906000805160206142ff8339815191529060200160405180910390a3505050565b6011805461087790613dd7565b6000843380612292612b72565b60405163abfa456f60e01b81526001600160a01b038581166004830152919091169063abfa456f90602401602060405180830381865afa1580156122da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fe9190613e11565b6001600160a01b03161461234f5760405162461bcd60e51b815260206004820152601860248201527757726f6e6720636f6e74726f6c6c6572206164647265737360401b6044820152606401610a0d565b61119b868686612f73565b6000338383612367612d8a565b6001600160a01b031663d794eb76848484601460009054906101000a900460ff166123a7896001600160a01b031660009081526005602052604090205490565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152604484019190915215156064830152608482015260a4016020604051808303816000875af115801561240a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242e9190613fca565b5061244461243c8787613072565b338888612ee8565b9695505050505050565b6000612458612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa1580156124a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c69190613e2e565b60ff1614806125405750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015612517573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253b9190613e2e565b60ff16145b61255c5760405162461bcd60e51b8152600401610a0d90613e4b565b6001600160a01b03851660009081526005602052604090205483111561258157600080fd5b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea86304e5bd6560056125a5612c5b565b8888886040518663ffffffff1660e01b81526004016125c89594939291906140d9565b60006040518083038186803b1580156125e057600080fd5b505af41580156125f4573d6000803e3d6000fd5b50505050846001600160a01b03167f809da7bb7ec71688d9e8dfe80575c8b28b33f0bfa28b2614e74d6f6c89dedee385858561262f8a612b7e565b60405161263f94939291906141bc565b60405180910390a2846001600160a01b03167f47e772fda56eb54ab211642ce5421882c49fc2b7033455982af14588ae4207ff84846040516126829291906138f6565b60405180910390a26040518381526000906001600160a01b038716906000805160206142ff8339815191529060200160405180910390a36116ca856000612d36565b6126cc613086565b6001600160a01b0316336001600160a01b03161461271d5760405162461bcd60e51b815260206004820152600e60248201526d139bdd08185d5d1a1bdc9a5e995960921b6044820152606401610a0d565b7f2fb5e8edf3c3b3026d4de746c621882add6265e6c90fa5bca2eb8b28bdfa2f1e828260405161274e9291906141f7565b60405180910390a15050565b3360009081526009602090815260408083206001600160a01b038616845290915281205461278990839061421b565b3360008181526009602090815260408083206001600160a01b038916808552908352928190208590555193845290927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259101610add565b6127e8613086565b6001600160a01b0316336001600160a01b0316146128395760405162461bcd60e51b815260206004820152600e60248201526d139bdd08185d5d1a1bdc9a5e995960921b6044820152606401610a0d565b604080518681526020810186905290810184905260608101839052608081018290526001600160a01b038716907fae3ec52864b589c8b6e1629e52fdab75882022b157ab46f166ca014c6ca0dbc59060a001610c17565b6003546001600160a01b031633146128ea5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a0d565b6128f381613093565b50565b6000612900612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa15801561294a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061296e9190613e2e565b60ff1614806129e85750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa1580156129bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e39190613e2e565b60ff16145b612a045760405162461bcd60e51b8152600401610a0d90613e4b565b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea86379a9ecab6005612a28612c5b565b898989896040518763ffffffff1660e01b8152600401612a4d96959493929190614233565b60006040518083038186803b158015612a6557600080fd5b505af4158015612a79573d6000803e3d6000fd5b50505050856001600160a01b03167f5c719d01bb88860dfca685ad3818d8b61a083caaf8f68abe6fa0fba4e40e33a9868585612ab48b612b7e565b604051612ac494939291906141bc565b60405180910390a2836001600160a01b0316866001600160a01b03167f5068c48f7f290ce2b8d555bd28014be9f312999bb621037ea3e9fc86335a21d78585604051612b119291906138f6565b60405180910390a3836001600160a01b0316866001600160a01b03166000805160206142ff83398151915285604051612b4c91815260200190565b60405180910390a3612b5e8685612d36565b505050505050565b6000611ff36001610c7f565b6000611ff36004610c7f565b6000612b88612b72565b60405163abfa456f60e01b81526001600160a01b038481166004830152919091169063abfa456f90602401602060405180830381865afa158015612bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf49190613e11565b6001600160a01b0316637f89a1856040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c559190613e2e565b92915050565b6040805160038082526080820190925260609160009190602082018480368337019050509050612c8b6008610c7f565b81600081518110612c9e57612c9e61415f565b60200260200101906001600160a01b031690816001600160a01b031681525050612cc86004610c7f565b81600181518110612cdb57612cdb61415f565b60200260200101906001600160a01b031690816001600160a01b031681525050612d06610800610c7f565b81600281518110612d1957612d1961415f565b6001600160a01b0390921660209283029190910190910152919050565b6001600160a01b038216600090815260056020526040902054600003612d5f57612d5f82613154565b6001600160a01b03811660009081526005602052604090205415612d8657612d8681613207565b5050565b6000611ff36008610c7f565b600080612da1613086565b9050336001600160a01b038216148015612e2d5750806001600160a01b031663851604cc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612df4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e189190613e11565b6001600160a01b0316856001600160a01b0316145b612ed4576001600160a01b0385166000908152600960209081526040808320338452909152902054831115612e9b5760405162461bcd60e51b81526020600482015260146024820152734e6f7420656e6f75676820616c6c6f77616e636560601b6044820152606401610a0d565b6001600160a01b038516600090815260096020908152604080832033845290915281208054859290612ece90849061412c565b90915550505b612edf85858561327b565b95945050505050565b60008415612efb57612efb848484613344565b612f058484612d36565b50929392505050565b6000611ff36040610c7f565b612f446002805460018101825560009190915260066000805160206142df83398151915290910155565b612f4c613410565b6002805460018101825560009190915260066000805160206142df83398151915290910155565b600080612f7e612b72565b60405163479ad3af60e11b81526001600160a01b0387811660048301529190911690638f35a75e90602401600060405180830381865afa158015612fc6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fee919081019061427b565b9050612ff98161348f565b61306757600061300882611c6a565b9050600084600181111561301e5761301e6142af565b036130345761302d858261421b565b9050613041565b61303e858261412c565b90505b806005600101836040516130559190614143565b90815260405190819003602001902055505b506001949350505050565b600061307f33848461327b565b9392505050565b6000611ff3610800610c7f565b6001600160a01b0381166130f85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a0d565b6003546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166000908152600c60205260409020548015612d8657600b548181146131be576000818152600a602090815260408083205485845281842080546001600160a01b0319166001600160a01b0390921691821790558352600c90915290208290555b6001600160a01b0383166000908152600c60209081526040808320839055838352600a909152902080546001600160a01b03191690556131ff60018261412c565b600b55505050565b6001600160a01b0381166000908152600c602052604081205490819003612d86576000600b546001613239919061421b565b6000818152600a6020908152604080832080546001600160a01b0389166001600160a01b031990911681179091558352600c9091529020819055600b55505050565b60006001600160a01b03831661329057600080fd5b6001600160a01b0384166000908152600560205260409020548211156132b557600080fd5b6001600160a01b038416600090815260056020526040812080548492906132dd90849061412c565b90915550506001600160a01b0383166000908152600560205260408120805484929061330a90849061421b565b92505081905550826001600160a01b0316846001600160a01b03166000805160206142ff83398151915284604051611c5891815260200190565b600073ebc72c3a7a8e5c615f200a12528d32b3c5c69ea86374796a67600561336a612b72565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b0390811660248301528088166044830152861660648201526084810185905260a401602060405180830381865af41580156133cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f091906142c5565b905080610f105761340384836001612f73565b506116ca83836000612f73565b600154600160a01b900460ff161561343a5760405162461bcd60e51b8152600401610a0d90613efb565b600380546001600160a01b031916339081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36001805460ff60a01b1916600160a01b179055565b6000612c55826040518060200160405280600081525060006134b0826134c1565b6134b9846134c1565b149392505050565b6000816040516020016134d49190614143565b604051602081830303815290604052805190602001209050919050565b8280546134fd90613dd7565b90600052602060002090601f01602090048101928261351f5760008555613565565b82601f1061353857805160ff1916838001178555613565565b82800160010185558215613565579182015b8281111561356557825182559160200191906001019061354a565b50613571929150613575565b5090565b5b808211156135715760008155600101613576565b60006020828403121561359c57600080fd5b5035919050565b60005b838110156135be5781810151838201526020016135a6565b83811115610f105750506000910152565b600081518084526135e78160208601602086016135a3565b601f01601f19169290920160200192915050565b60208152600061307f60208301846135cf565b6001600160a01b03811681146128f357600080fd5b6000806040838503121561363657600080fd5b8235915060208301356136488161360e565b809150509250929050565b6000806040838503121561366657600080fd5b82356136718161360e565b946020939093013593505050565b6000806000806080858703121561369557600080fd5b84356136a08161360e565b935060208501356136b08161360e565b925060408501356136c08161360e565b9396929550929360600135925050565b6020808252825182820181905260009190848201906040850190845b81811015613708578351835292840192918401916001016136ec565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561375257613752613714565b604052919050565b60006001600160401b0382111561377357613773613714565b50601f01601f191660200190565b600082601f83011261379257600080fd5b81356137a56137a08261375a565b61372a565b8181528460208386010111156137ba57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000606084860312156137ec57600080fd5b83356137f78161360e565b92506020840135915060408401356001600160401b0381111561381957600080fd5b61382586828701613781565b9150509250925092565b60ff811681146128f357600080fd5b60008060006060848603121561385357600080fd5b83356001600160401b038082111561386a57600080fd5b61387687838801613781565b9450602086013591508082111561388c57600080fd5b5061389986828701613781565b92505060408401356138aa8161382f565b809150509250925092565b6000806000606084860312156138ca57600080fd5b83356138d58161360e565b925060208401356138e58161360e565b929592945050506040919091013590565b82815260406020820152600061390f60408301846135cf565b949350505050565b60006001600160401b0382111561393057613930613714565b5060051b60200190565b80356001600160401b038116811461395157600080fd5b919050565b600082601f83011261396757600080fd5b813560206139776137a083613917565b82815260059290921b8401810191818101908684111561399657600080fd5b8286015b848110156139b8576139ab8161393a565b835291830191830161399a565b509695505050505050565b60008060008060008060c087890312156139dc57600080fd5b86356139e78161360e565b955060208781013595506040880135945060608801356001600160401b0380821115613a1257600080fd5b818a0191508a601f830112613a2657600080fd5b8135613a346137a082613917565b81815260059190911b8301840190848101908d831115613a5357600080fd5b938501935b82851015613a7157843582529385019390850190613a58565b9750505060808a0135925080831115613a8957600080fd5b613a958b848c01613781565b945060a08a0135925080831115613aab57600080fd5b5050613ab989828a01613956565b9150509295509295509295565b60008060008060808587031215613adc57600080fd5b8435613ae78161360e565b93506020850135613af78161360e565b92506040850135915060608501356001600160401b03811115613b1957600080fd5b613b2587828801613781565b91505092959194509250565b80151581146128f357600080fd5b60008060408385031215613b5257600080fd5b8235613b5d8161382f565b9150602083013561364881613b31565b600060208284031215613b7f57600080fd5b81356001600160401b03811115613b9557600080fd5b61390f84828501613781565b600060208284031215613bb357600080fd5b813561307f8161360e565b60008060008060008060c08789031215613bd757600080fd5b8635613be28161360e565b955060208701359450604087013593506060870135925060808701356001600160401b03811115613c1257600080fd5b613c1e89828a01613781565b925050613c2d60a0880161393a565b90509295509295509295565b60008060008060808587031215613c4f57600080fd5b8435613c5a8161360e565b93506020850135613c6a8161360e565b925060408501359150606085013560028110613c8557600080fd5b939692955090935050565b60008060408385031215613ca357600080fd5b8235613cae8161360e565b915060208301356001600160401b03811115613cc957600080fd5b613cd585828601613781565b9150509250929050565b60008060408385031215613cf257600080fd5b8235613cfd8161360e565b915060208301356136488161360e565b60008060008060008060c08789031215613d2657600080fd5b8635613d318161360e565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b600080600080600060a08688031215613d7157600080fd5b8535613d7c8161360e565b94506020860135613d8c8161360e565b93506040860135613d9c8161360e565b92506060860135915060808601356001600160401b03811115613dbe57600080fd5b613dca88828901613781565b9150509295509295909350565b600181811c90821680613deb57607f821691505b602082108103613e0b57634e487b7160e01b600052602260045260246000fd5b50919050565b600060208284031215613e2357600080fd5b815161307f8161360e565b600060208284031215613e4057600080fd5b815161307f8161382f565b60208082526018908201527f496e73756666696369656e74207472757374206c6576656c0000000000000000604082015260600190565b600081518084526020808501945080840160005b83811015613ebb5781516001600160a01b031687529582019590820190600101613e96565b509495945050505050565b848152608060208201526000613edf6080830186613e82565b6001600160a01b03949094166040830152506060015292915050565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b600082601f830112613f5a57600080fd5b8151613f686137a08261375a565b818152846020838601011115613f7d57600080fd5b61390f8260208301602087016135a3565b60008060408385031215613fa157600080fd5b8251915060208301516001600160401b03811115613fbe57600080fd5b613cd585828601613f49565b600060208284031215613fdc57600080fd5b815161307f81613b31565b600081518084526020808501945080840160005b83811015613ebb5781516001600160401b031687529582019590820190600101613ffb565b60006101408c83526020818185015261403b8285018e613e82565b6001600160a01b038d811660408701528c166060860152608085018b905260a085018a905284810360c08601528851808252828a0193509082019060005b8181101561409557845183529383019391830191600101614079565b505084810360e08601526140a98189613fe7565b925050508281036101008401526140c081866135cf565b915050826101208301529b9a5050505050505050505050565b85815260a0602082015260006140f260a0830187613e82565b6001600160a01b039586166040840152939094166060820152608001529392505050565b634e487b7160e01b600052601160045260246000fd5b60008282101561413e5761413e614116565b500390565b600082516141558184602087016135a3565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b86815260c06020820152600061418e60c0830188613e82565b6001600160a01b03969096166040830152506060810193909352608083019190915260a09091015292915050565b60018060a01b03851681528360208201526080604082015260006141e360808301856135cf565b905060ff8316606083015295945050505050565b6001600160a01b038316815260406020820181905260009061390f908301846135cf565b6000821982111561422e5761422e614116565b500190565b86815260c06020820152600061424c60c0830188613e82565b6001600160a01b03968716604084015294861660608301525091909316608082015260a0019190915292915050565b60006020828403121561428d57600080fd5b81516001600160401b038111156142a357600080fd5b61390f84828501613f49565b634e487b7160e01b600052602160045260246000fd5b6000602082840312156142d757600080fd5b505191905056fe405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5aceddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122068bb28db9a71588dc05c8783d5e4ba4d25019ddc053bbc68e3291a98bfbfa30764736f6c634300080d0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103f15760003560e01c8063712d5fa211610215578063ae22901d11610125578063ce606ee0116100b8578063dd62ed3e11610087578063dd62ed3e146107b8578063f11d785c146107f1578063f2fde38b14610804578063f5be319314610817578063fbb24bf41461081f57600080fd5b8063ce606ee014610784578063d3f61d7014610795578063d73dd6231461079d578063d8486d29146107b057600080fd5b8063b9683af0116100f4578063b9683af01461074d578063c4b8c5a014610760578063c754015014610768578063cc1bbe491461077157600080fd5b8063ae22901d14610729578063b187bd2614610732578063b696bf021461073d578063b8632a041461074557600080fd5b8063897c002e116101a857806395d89b411161017757806395d89b41146106ea5780639aa25f25146106f25780639c37b8e114610705578063a9059cbb1461070d578063add377391461072057600080fd5b8063897c002e146106b45780638da5cb5b146106bc5780638f32d59b146106c457806393af4a47146106d757600080fd5b8063794d3850116101e4578063794d3850146106945780637f4072351461069c5780638129fc1c146106a45780638456cb59146106ac57600080fd5b8063712d5fa214610667578063715018a61461067a5780637627f6c41461068257806377cc16e01461068c57600080fd5b806329b57c691161031057806340801b6c116102a35780634c83c126116102725780634c83c126146105fc57806359fefa471461060557806366188463146106185780636f2968981461062b57806370a082311461063e57600080fd5b806340801b6c146105c6578063475a9fa9146105ce57806347786d37146105e157806349ce2a16146105f457600080fd5b80633ce5aae9116102df5780633ce5aae91461059a5780633f4ba83a146105ad5780633f727f24146105b55780634021d0a2146105be57600080fd5b806329b57c6914610557578063313ce5671461055f578063355274ea1461057e578063356c52b01461058757600080fd5b8063158ef93e1161038857806318160ddd1161035757806318160ddd146105085780631f227b431461051057806323b872dd1461053157806324ffea9a1461054457600080fd5b8063158ef93e146104c557806315f570dc146104d95780631624f6c6146104ec5780631722957f146104ff57600080fd5b8063095ea7b3116103c4578063095ea7b3146104755780630bffae76146104885780630d8e6e2c1461049d5780630e5324be146104b257600080fd5b8063023f8fd1146103f657806306fdde031461042657806307a8db0a1461043b578063082af7c014610452575b600080fd5b61040961040436600461358a565b610832565b6040516001600160a01b0390911681526020015b60405180910390f35b61042e61086a565b60405161041d91906135fb565b61044461400081565b60405190815260200161041d565b610465610460366004613623565b6108f8565b604051901515815260200161041d565b610465610483366004613653565b610a82565b61049b61049636600461367f565b610aee565b005b6104a5610c27565b60405161041d91906136d0565b6104096104c036600461358a565b610c7f565b60015461046590600160a01b900460ff1681565b61049b6104e73660046137d7565b610c9a565b61049b6104fa36600461383e565b610f16565b61044461080081565b600754610444565b61052361051e3660046138b5565b611019565b60405161041d9291906138f6565b61046561053f3660046138b5565b6110b0565b6104656105523660046139c3565b6111a6565b600b54610444565b60125461056c9060ff1681565b60405160ff909116815260200161041d565b610444600f5481565b61049b61059536600461358a565b611399565b61049b6105a8366004613ac6565b6114b3565b61049b6116d1565b61044461200081565b610444600281565b61056c600181565b6104656105dc366004613653565b611860565b61049b6105ef36600461358a565b61188b565b610444608081565b61044461040081565b61049b610613366004613b3f565b6119f4565b610465610626366004613653565b611b81565b610444610639366004613b6d565b611c6a565b61044461064c366004613ba1565b6001600160a01b031660009081526005602052604090205490565b610465610675366004613bbe565b611c95565b61049b611d53565b6013546104449081565b61056c600081565b61056c600281565b610444604081565b61049b611df7565b61049b611e50565b610444600481565b610409611fdf565b6003546001600160a01b03163314610465565b61049b6106e5366004613653565b611ff8565b61042e612278565b610465610700366004613c39565b612285565b610444602081565b61046561071b366004613653565b61235a565b61044461020081565b61044461100081565b60145460ff16610465565b610444600181565b610444600881565b61049b61075b366004613ac6565b61244e565b610444601081565b61044461010081565b61049b61077f366004613c90565b6126c4565b6003546001600160a01b0316610409565b61056c600481565b6104656107ab366004613653565b61275a565b61056c600881565b6104446107c6366004613cdf565b6001600160a01b03918216600090815260096020908152604080832093909416825291909152205490565b61049b6107ff366004613d0d565b6127e0565b61049b610812366004613ba1565b612890565b600854610444565b61049b61082d366004613d59565b6128f6565b600080821180156108455750600b548211155b61084e57600080fd5b506000908152600a60205260409020546001600160a01b031690565b6010805461087790613dd7565b80601f01602080910402602001604051908101604052809291908181526020018280546108a390613dd7565b80156108f05780601f106108c5576101008083540402835291602001916108f0565b820191906000526020600020905b8154815290600101906020018083116108d357829003601f168201915b505050505081565b600080610903612b66565b9050336001600160a01b0316306001600160a01b031663ce606ee06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561094d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109719190613e11565b6001600160a01b031614806109f15750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa1580156109c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ec9190613e2e565b60ff16145b610a165760405162461bcd60e51b8152600401610a0d90613e4b565b60405180910390fd5b60008481526004602090815260409182902080546001600160a01b0319166001600160a01b0387169081179091558251878152918201527f8a9dba1dc2a1daab74cedc87602df39dcebeacc96d1f5bf104159897a96bebaf910160405180910390a15060019392505050565b3360008181526009602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610add9086815260200190565b60405180910390a350600192915050565b833380610af9612b72565b60405163abfa456f60e01b81526001600160a01b038581166004830152919091169063abfa456f90602401602060405180830381865afa158015610b41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b659190613e11565b6001600160a01b031614610bb65760405162461bcd60e51b815260206004820152601860248201527757726f6e6720636f6e74726f6c6c6572206164647265737360401b6044820152606401610a0d565b856001600160a01b03167fa9ef15dd6e8530645f6476ab6ac36f1cb5acefe0eef5bf5c04664bb251ea01db868686610bed8b612b7e565b604080516001600160a01b0395861681529490931660208501529183015260ff1660608201526080015b60405180910390a2505050505050565b60606002805480602002602001604051908101604052809291908181526020018280548015610c7557602002820191906000526020600020905b815481526020019060010190808311610c61575b5050505050905090565b6000908152600460205260409020546001600160a01b031690565b6000610ca4612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa158015610cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d129190613e2e565b60ff161480610d8c5750604051634427673360e01b81523360048201526002906001600160a01b03831690634427673390602401602060405180830381865afa158015610d63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d879190613e2e565b60ff16145b80610e025750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015610dd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfd9190613e2e565b60ff16145b610e1e5760405162461bcd60e51b8152600401610a0d90613e4b565b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea8638948a4696005610e42612c5b565b87876040518563ffffffff1660e01b8152600401610e639493929190613ec6565b60006040518083038186803b158015610e7b57600080fd5b505af4158015610e8f573d6000803e3d6000fd5b50505050836001600160a01b03167f47e772fda56eb54ab211642ce5421882c49fc2b7033455982af14588ae4207ff8484604051610ece9291906138f6565b60405180910390a26040518381526000906001600160a01b038616906000805160206142ff8339815191529060200160405180910390a3610f10846000612d36565b50505050565b600154600160a01b900460ff1615610f405760405162461bcd60e51b8152600401610a0d90613efb565b6000546001600160a01b0316610f985760405162461bcd60e51b815260206004820152601e60248201527f4d75737420626520696e697469616c697a65642066726f6d2070726f787900006044820152606401610a0d565b610fa0611df7565b6002805460018101825560009190915260056000805160206142df833981519152909101558251610fd89060109060208601906134f1565b508151610fec9060119060208501906134f1565b506012805460ff90921660ff1990921691909117905550506001805460ff60a01b1916600160a01b179055565b60006060611025612d8a565b604051631f227b4360e01b81526001600160a01b0387811660048301528681166024830152604482018690529190911690631f227b4390606401600060405180830381865afa15801561107c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110a49190810190613f8e565b91509150935093915050565b60008383836110bd612d8a565b6001600160a01b031663d794eb76848484601460009054906101000a900460ff166110fd896001600160a01b031660009081526005602052604090205490565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152604484019190915215156064830152608482015260a4016020604051808303816000875af1158015611160573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111849190613fca565b5061119b611193888888612d96565b888888612ee8565b979650505050505050565b6000806111b1612b66565b604051634427673360e01b81523360048201529091506002906001600160a01b03831690634427673390602401602060405180830381865afa1580156111fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121f9190613e2e565b60ff1614806112995750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015611270573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112949190613e2e565b60ff16145b6112b55760405162461bcd60e51b8152600401610a0d90613e4b565b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea86385e9c5bf60056112d9612c5b565b6112e1612f0e565b8c8c8c8c8b8d600f546040518b63ffffffff1660e01b815260040161130f9a99989796959493929190614020565b602060405180830381865af415801561132c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113509190613fca565b506040518781526001600160a01b038916906000906000805160206142ff8339815191529060200160405180910390a361138b600089612d36565b506001979650505050505050565b60006113a3612b66565b9050336001600160a01b0316306001600160a01b031663ce606ee06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114119190613e11565b6001600160a01b031614806114915750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015611468573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148c9190613e2e565b60ff16145b6114ad5760405162461bcd60e51b8152600401610a0d90613e4b565b50601355565b60006114bd612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa158015611507573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152b9190613e2e565b60ff1614806115a55750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa15801561157c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a09190613e2e565b60ff16145b6115c15760405162461bcd60e51b8152600401610a0d90613e4b565b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea8638d876d3860056115e5612c5b565b8888886040518663ffffffff1660e01b81526004016116089594939291906140d9565b60006040518083038186803b15801561162057600080fd5b505af4158015611634573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b03167f5068c48f7f290ce2b8d555bd28014be9f312999bb621037ea3e9fc86335a21d7858560405161167d9291906138f6565b60405180910390a3836001600160a01b0316856001600160a01b03166000805160206142ff833981519152856040516116b891815260200190565b60405180910390a36116ca8585612d36565b5050505050565b60006116db612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa158015611725573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117499190613e2e565b60ff1614806117c35750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa15801561179a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117be9190613e2e565b60ff16145b6117df5760405162461bcd60e51b8152600401610a0d90613e4b565b60145460ff1661182a5760405162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9858dd081a5cc81b9bdd081c185d5cd95960521b6044820152606401610a0d565b6014805460ff191690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a150565b60006118818383426000604051806020016040528060008152506000611c95565b5060019392505050565b6000611895612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa1580156118df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119039190613e2e565b60ff16148061197d5750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015611954573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119789190613e2e565b60ff16145b6119995760405162461bcd60e51b8152600401610a0d90613e4b565b600f54156119e15760405162461bcd60e51b8152602060048201526015602482015274151bdad95b8818d85c08185b1c9958591e481cd95d605a1b6044820152606401610a0d565b600082116119ee57600080fd5b50600f55565b60006119fe612b66565b9050336001600160a01b0316306001600160a01b031663ce606ee06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6c9190613e11565b6001600160a01b03161480611aec5750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015611ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae79190613e2e565b60ff16145b611b085760405162461bcd60e51b8152600401610a0d90613e4b565b604051635eafc2b960e11b81526013600482015260ff84166024820152821515604482015273ebc72c3a7a8e5c615f200a12528d32b3c5c69ea89063bd5f85729060640160006040518083038186803b158015611b6457600080fd5b505af4158015611b78573d6000803e3d6000fd5b50505050505050565b3360009081526009602090815260408083206001600160a01b038616845290915281205480831115611bd6573360009081526009602090815260408083206001600160a01b0388168452909152812055611c05565b611be0838261412c565b3360009081526009602090815260408083206001600160a01b03891684529091529020555b3360008181526009602090815260408083206001600160a01b038916808552908352928190205490519081529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a35060019392505050565b6000600560010182604051611c7f9190614143565b9081526020016040518091039020549050919050565b60006060808515611d3557604080516001808252818301909252906020808301908036833750506040805160018082528183019092529294509050602080830190803683370190505090508582600081518110611cf457611cf461415f565b6020026020010181815250508381600081518110611d1457611d1461415f565b60200260200101906001600160401b031690816001600160401b0316815250505b611d438989898589866111a6565b5060019998505050505050505050565b6003546001600160a01b03163314611dad5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a0d565b6003546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600380546001600160a01b0319169055565b611e216002805460018101825560009190915260036000805160206142df83398151915290910155565b611e29612f1a565b6002805460018101825560009190915260056000805160206142df83398151915290910155565b6000611e5a612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa158015611ea4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec89190613e2e565b60ff161480611f425750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015611f19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3d9190613e2e565b60ff16145b611f5e5760405162461bcd60e51b8152600401610a0d90613e4b565b60145460ff1615611fa65760405162461bcd60e51b815260206004820152601260248201527110dbdb9d1c9858dd081a5cc81c185d5cd95960721b6044820152606401610a0d565b6014805460ff191660011790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a150565b6000611ff36003546001600160a01b031690565b905090565b6000612002612b66565b604051634427673360e01b81523360048201529091506002906001600160a01b03831690634427673390602401602060405180830381865afa15801561204c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120709190613e2e565b60ff1614806120ea5750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa1580156120c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e59190613e2e565b60ff16145b6121065760405162461bcd60e51b8152600401610a0d90613e4b565b61210e612b72565b6040516333955c3b60e21b81526001600160a01b038581166004830152919091169063ce5570ec90602401602060405180830381865afa158015612156573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217a9190613fca565b6121b75760405162461bcd60e51b815260206004820152600e60248201526d155b9adb9bdddb881dd85b1b195d60921b6044820152606401610a0d565b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea863678661c860056121db612c5b565b868642600f546040518763ffffffff1660e01b815260040161220296959493929190614175565b602060405180830381865af415801561221f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122439190613fca565b506040518281526001600160a01b038416906000906000805160206142ff8339815191529060200160405180910390a3505050565b6011805461087790613dd7565b6000843380612292612b72565b60405163abfa456f60e01b81526001600160a01b038581166004830152919091169063abfa456f90602401602060405180830381865afa1580156122da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fe9190613e11565b6001600160a01b03161461234f5760405162461bcd60e51b815260206004820152601860248201527757726f6e6720636f6e74726f6c6c6572206164647265737360401b6044820152606401610a0d565b61119b868686612f73565b6000338383612367612d8a565b6001600160a01b031663d794eb76848484601460009054906101000a900460ff166123a7896001600160a01b031660009081526005602052604090205490565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152604484019190915215156064830152608482015260a4016020604051808303816000875af115801561240a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242e9190613fca565b5061244461243c8787613072565b338888612ee8565b9695505050505050565b6000612458612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa1580156124a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c69190613e2e565b60ff1614806125405750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa158015612517573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253b9190613e2e565b60ff16145b61255c5760405162461bcd60e51b8152600401610a0d90613e4b565b6001600160a01b03851660009081526005602052604090205483111561258157600080fd5b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea86304e5bd6560056125a5612c5b565b8888886040518663ffffffff1660e01b81526004016125c89594939291906140d9565b60006040518083038186803b1580156125e057600080fd5b505af41580156125f4573d6000803e3d6000fd5b50505050846001600160a01b03167f809da7bb7ec71688d9e8dfe80575c8b28b33f0bfa28b2614e74d6f6c89dedee385858561262f8a612b7e565b60405161263f94939291906141bc565b60405180910390a2846001600160a01b03167f47e772fda56eb54ab211642ce5421882c49fc2b7033455982af14588ae4207ff84846040516126829291906138f6565b60405180910390a26040518381526000906001600160a01b038716906000805160206142ff8339815191529060200160405180910390a36116ca856000612d36565b6126cc613086565b6001600160a01b0316336001600160a01b03161461271d5760405162461bcd60e51b815260206004820152600e60248201526d139bdd08185d5d1a1bdc9a5e995960921b6044820152606401610a0d565b7f2fb5e8edf3c3b3026d4de746c621882add6265e6c90fa5bca2eb8b28bdfa2f1e828260405161274e9291906141f7565b60405180910390a15050565b3360009081526009602090815260408083206001600160a01b038616845290915281205461278990839061421b565b3360008181526009602090815260408083206001600160a01b038916808552908352928190208590555193845290927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259101610add565b6127e8613086565b6001600160a01b0316336001600160a01b0316146128395760405162461bcd60e51b815260206004820152600e60248201526d139bdd08185d5d1a1bdc9a5e995960921b6044820152606401610a0d565b604080518681526020810186905290810184905260608101839052608081018290526001600160a01b038716907fae3ec52864b589c8b6e1629e52fdab75882022b157ab46f166ca014c6ca0dbc59060a001610c17565b6003546001600160a01b031633146128ea5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a0d565b6128f381613093565b50565b6000612900612b66565b604051634427673360e01b81523360048201529091506008906001600160a01b03831690634427673390602401602060405180830381865afa15801561294a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061296e9190613e2e565b60ff1614806129e85750604051634427673360e01b81523360048201526001906001600160a01b03831690634427673390602401602060405180830381865afa1580156129bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e39190613e2e565b60ff16145b612a045760405162461bcd60e51b8152600401610a0d90613e4b565b73ebc72c3a7a8e5c615f200a12528d32b3c5c69ea86379a9ecab6005612a28612c5b565b898989896040518763ffffffff1660e01b8152600401612a4d96959493929190614233565b60006040518083038186803b158015612a6557600080fd5b505af4158015612a79573d6000803e3d6000fd5b50505050856001600160a01b03167f5c719d01bb88860dfca685ad3818d8b61a083caaf8f68abe6fa0fba4e40e33a9868585612ab48b612b7e565b604051612ac494939291906141bc565b60405180910390a2836001600160a01b0316866001600160a01b03167f5068c48f7f290ce2b8d555bd28014be9f312999bb621037ea3e9fc86335a21d78585604051612b119291906138f6565b60405180910390a3836001600160a01b0316866001600160a01b03166000805160206142ff83398151915285604051612b4c91815260200190565b60405180910390a3612b5e8685612d36565b505050505050565b6000611ff36001610c7f565b6000611ff36004610c7f565b6000612b88612b72565b60405163abfa456f60e01b81526001600160a01b038481166004830152919091169063abfa456f90602401602060405180830381865afa158015612bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf49190613e11565b6001600160a01b0316637f89a1856040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c559190613e2e565b92915050565b6040805160038082526080820190925260609160009190602082018480368337019050509050612c8b6008610c7f565b81600081518110612c9e57612c9e61415f565b60200260200101906001600160a01b031690816001600160a01b031681525050612cc86004610c7f565b81600181518110612cdb57612cdb61415f565b60200260200101906001600160a01b031690816001600160a01b031681525050612d06610800610c7f565b81600281518110612d1957612d1961415f565b6001600160a01b0390921660209283029190910190910152919050565b6001600160a01b038216600090815260056020526040902054600003612d5f57612d5f82613154565b6001600160a01b03811660009081526005602052604090205415612d8657612d8681613207565b5050565b6000611ff36008610c7f565b600080612da1613086565b9050336001600160a01b038216148015612e2d5750806001600160a01b031663851604cc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612df4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e189190613e11565b6001600160a01b0316856001600160a01b0316145b612ed4576001600160a01b0385166000908152600960209081526040808320338452909152902054831115612e9b5760405162461bcd60e51b81526020600482015260146024820152734e6f7420656e6f75676820616c6c6f77616e636560601b6044820152606401610a0d565b6001600160a01b038516600090815260096020908152604080832033845290915281208054859290612ece90849061412c565b90915550505b612edf85858561327b565b95945050505050565b60008415612efb57612efb848484613344565b612f058484612d36565b50929392505050565b6000611ff36040610c7f565b612f446002805460018101825560009190915260066000805160206142df83398151915290910155565b612f4c613410565b6002805460018101825560009190915260066000805160206142df83398151915290910155565b600080612f7e612b72565b60405163479ad3af60e11b81526001600160a01b0387811660048301529190911690638f35a75e90602401600060405180830381865afa158015612fc6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fee919081019061427b565b9050612ff98161348f565b61306757600061300882611c6a565b9050600084600181111561301e5761301e6142af565b036130345761302d858261421b565b9050613041565b61303e858261412c565b90505b806005600101836040516130559190614143565b90815260405190819003602001902055505b506001949350505050565b600061307f33848461327b565b9392505050565b6000611ff3610800610c7f565b6001600160a01b0381166130f85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a0d565b6003546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166000908152600c60205260409020548015612d8657600b548181146131be576000818152600a602090815260408083205485845281842080546001600160a01b0319166001600160a01b0390921691821790558352600c90915290208290555b6001600160a01b0383166000908152600c60209081526040808320839055838352600a909152902080546001600160a01b03191690556131ff60018261412c565b600b55505050565b6001600160a01b0381166000908152600c602052604081205490819003612d86576000600b546001613239919061421b565b6000818152600a6020908152604080832080546001600160a01b0389166001600160a01b031990911681179091558352600c9091529020819055600b55505050565b60006001600160a01b03831661329057600080fd5b6001600160a01b0384166000908152600560205260409020548211156132b557600080fd5b6001600160a01b038416600090815260056020526040812080548492906132dd90849061412c565b90915550506001600160a01b0383166000908152600560205260408120805484929061330a90849061421b565b92505081905550826001600160a01b0316846001600160a01b03166000805160206142ff83398151915284604051611c5891815260200190565b600073ebc72c3a7a8e5c615f200a12528d32b3c5c69ea86374796a67600561336a612b72565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b0390811660248301528088166044830152861660648201526084810185905260a401602060405180830381865af41580156133cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f091906142c5565b905080610f105761340384836001612f73565b506116ca83836000612f73565b600154600160a01b900460ff161561343a5760405162461bcd60e51b8152600401610a0d90613efb565b600380546001600160a01b031916339081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36001805460ff60a01b1916600160a01b179055565b6000612c55826040518060200160405280600081525060006134b0826134c1565b6134b9846134c1565b149392505050565b6000816040516020016134d49190614143565b604051602081830303815290604052805190602001209050919050565b8280546134fd90613dd7565b90600052602060002090601f01602090048101928261351f5760008555613565565b82601f1061353857805160ff1916838001178555613565565b82800160010185558215613565579182015b8281111561356557825182559160200191906001019061354a565b50613571929150613575565b5090565b5b808211156135715760008155600101613576565b60006020828403121561359c57600080fd5b5035919050565b60005b838110156135be5781810151838201526020016135a6565b83811115610f105750506000910152565b600081518084526135e78160208601602086016135a3565b601f01601f19169290920160200192915050565b60208152600061307f60208301846135cf565b6001600160a01b03811681146128f357600080fd5b6000806040838503121561363657600080fd5b8235915060208301356136488161360e565b809150509250929050565b6000806040838503121561366657600080fd5b82356136718161360e565b946020939093013593505050565b6000806000806080858703121561369557600080fd5b84356136a08161360e565b935060208501356136b08161360e565b925060408501356136c08161360e565b9396929550929360600135925050565b6020808252825182820181905260009190848201906040850190845b81811015613708578351835292840192918401916001016136ec565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561375257613752613714565b604052919050565b60006001600160401b0382111561377357613773613714565b50601f01601f191660200190565b600082601f83011261379257600080fd5b81356137a56137a08261375a565b61372a565b8181528460208386010111156137ba57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000606084860312156137ec57600080fd5b83356137f78161360e565b92506020840135915060408401356001600160401b0381111561381957600080fd5b61382586828701613781565b9150509250925092565b60ff811681146128f357600080fd5b60008060006060848603121561385357600080fd5b83356001600160401b038082111561386a57600080fd5b61387687838801613781565b9450602086013591508082111561388c57600080fd5b5061389986828701613781565b92505060408401356138aa8161382f565b809150509250925092565b6000806000606084860312156138ca57600080fd5b83356138d58161360e565b925060208401356138e58161360e565b929592945050506040919091013590565b82815260406020820152600061390f60408301846135cf565b949350505050565b60006001600160401b0382111561393057613930613714565b5060051b60200190565b80356001600160401b038116811461395157600080fd5b919050565b600082601f83011261396757600080fd5b813560206139776137a083613917565b82815260059290921b8401810191818101908684111561399657600080fd5b8286015b848110156139b8576139ab8161393a565b835291830191830161399a565b509695505050505050565b60008060008060008060c087890312156139dc57600080fd5b86356139e78161360e565b955060208781013595506040880135945060608801356001600160401b0380821115613a1257600080fd5b818a0191508a601f830112613a2657600080fd5b8135613a346137a082613917565b81815260059190911b8301840190848101908d831115613a5357600080fd5b938501935b82851015613a7157843582529385019390850190613a58565b9750505060808a0135925080831115613a8957600080fd5b613a958b848c01613781565b945060a08a0135925080831115613aab57600080fd5b5050613ab989828a01613956565b9150509295509295509295565b60008060008060808587031215613adc57600080fd5b8435613ae78161360e565b93506020850135613af78161360e565b92506040850135915060608501356001600160401b03811115613b1957600080fd5b613b2587828801613781565b91505092959194509250565b80151581146128f357600080fd5b60008060408385031215613b5257600080fd5b8235613b5d8161382f565b9150602083013561364881613b31565b600060208284031215613b7f57600080fd5b81356001600160401b03811115613b9557600080fd5b61390f84828501613781565b600060208284031215613bb357600080fd5b813561307f8161360e565b60008060008060008060c08789031215613bd757600080fd5b8635613be28161360e565b955060208701359450604087013593506060870135925060808701356001600160401b03811115613c1257600080fd5b613c1e89828a01613781565b925050613c2d60a0880161393a565b90509295509295509295565b60008060008060808587031215613c4f57600080fd5b8435613c5a8161360e565b93506020850135613c6a8161360e565b925060408501359150606085013560028110613c8557600080fd5b939692955090935050565b60008060408385031215613ca357600080fd5b8235613cae8161360e565b915060208301356001600160401b03811115613cc957600080fd5b613cd585828601613781565b9150509250929050565b60008060408385031215613cf257600080fd5b8235613cfd8161360e565b915060208301356136488161360e565b60008060008060008060c08789031215613d2657600080fd5b8635613d318161360e565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b600080600080600060a08688031215613d7157600080fd5b8535613d7c8161360e565b94506020860135613d8c8161360e565b93506040860135613d9c8161360e565b92506060860135915060808601356001600160401b03811115613dbe57600080fd5b613dca88828901613781565b9150509295509295909350565b600181811c90821680613deb57607f821691505b602082108103613e0b57634e487b7160e01b600052602260045260246000fd5b50919050565b600060208284031215613e2357600080fd5b815161307f8161360e565b600060208284031215613e4057600080fd5b815161307f8161382f565b60208082526018908201527f496e73756666696369656e74207472757374206c6576656c0000000000000000604082015260600190565b600081518084526020808501945080840160005b83811015613ebb5781516001600160a01b031687529582019590820190600101613e96565b509495945050505050565b848152608060208201526000613edf6080830186613e82565b6001600160a01b03949094166040830152506060015292915050565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b600082601f830112613f5a57600080fd5b8151613f686137a08261375a565b818152846020838601011115613f7d57600080fd5b61390f8260208301602087016135a3565b60008060408385031215613fa157600080fd5b8251915060208301516001600160401b03811115613fbe57600080fd5b613cd585828601613f49565b600060208284031215613fdc57600080fd5b815161307f81613b31565b600081518084526020808501945080840160005b83811015613ebb5781516001600160401b031687529582019590820190600101613ffb565b60006101408c83526020818185015261403b8285018e613e82565b6001600160a01b038d811660408701528c166060860152608085018b905260a085018a905284810360c08601528851808252828a0193509082019060005b8181101561409557845183529383019391830191600101614079565b505084810360e08601526140a98189613fe7565b925050508281036101008401526140c081866135cf565b915050826101208301529b9a5050505050505050505050565b85815260a0602082015260006140f260a0830187613e82565b6001600160a01b039586166040840152939094166060820152608001529392505050565b634e487b7160e01b600052601160045260246000fd5b60008282101561413e5761413e614116565b500390565b600082516141558184602087016135a3565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b86815260c06020820152600061418e60c0830188613e82565b6001600160a01b03969096166040830152506060810193909352608083019190915260a09091015292915050565b60018060a01b03851681528360208201526080604082015260006141e360808301856135cf565b905060ff8316606083015295945050505050565b6001600160a01b038316815260406020820181905260009061390f908301846135cf565b6000821982111561422e5761422e614116565b500190565b86815260c06020820152600061424c60c0830188613e82565b6001600160a01b03968716604084015294861660608301525091909316608082015260a0019190915292915050565b60006020828403121561428d57600080fd5b81516001600160401b038111156142a357600080fd5b61390f84828501613f49565b634e487b7160e01b600052602160045260246000fd5b6000602082840312156142d757600080fd5b505191905056fe405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5aceddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122068bb28db9a71588dc05c8783d5e4ba4d25019ddc053bbc68e3291a98bfbfa30764736f6c634300080d0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.