Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 32901359 | 194 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ShareClassManager
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 1 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import {Auth} from "src/misc/Auth.sol";
import {D18, d18} from "src/misc/types/D18.sol";
import {CastLib} from "src/misc/libraries/CastLib.sol";
import {MathLib} from "src/misc/libraries/MathLib.sol";
import {BytesLib} from "src/misc/libraries/BytesLib.sol";
import {PoolId} from "src/common/types/PoolId.sol";
import {AssetId} from "src/common/types/AssetId.sol";
import {PricingLib} from "src/common/libraries/PricingLib.sol";
import {ShareClassId, newShareClassId} from "src/common/types/ShareClassId.sol";
import {IHubRegistry} from "src/hub/interfaces/IHubRegistry.sol";
import {
IShareClassManager,
EpochInvestAmounts,
EpochRedeemAmounts,
UserOrder,
ShareClassMetadata,
ShareClassMetrics,
QueuedOrder,
RequestType,
EpochId
} from "src/hub/interfaces/IShareClassManager.sol";
/// @title Share Class Manager
/// @notice Manager for the share classes of a pool, and the core logic for tracking, approving, and fulfilling
/// requests.
contract ShareClassManager is Auth, IShareClassManager {
using MathLib for *;
using CastLib for *;
using BytesLib for bytes;
IHubRegistry public immutable hubRegistry;
// Share classes
mapping(bytes32 salt => bool) public salts;
mapping(PoolId poolId => uint32) public shareClassCount;
mapping(ShareClassId scId => ShareClassMetrics) public metrics;
mapping(ShareClassId scId => ShareClassMetadata) public metadata;
mapping(PoolId poolId => mapping(ShareClassId => bool)) public shareClassIds;
mapping(ShareClassId scId => mapping(uint16 centrifugeId => uint128)) public issuance;
// Epochs
mapping(ShareClassId scId => mapping(AssetId assetId => EpochId)) public epochId;
mapping(ShareClassId scId => mapping(AssetId assetId => mapping(uint32 epochId_ => EpochInvestAmounts epoch)))
public epochInvestAmounts;
mapping(ShareClassId scId => mapping(AssetId assetId => mapping(uint32 epochId_ => EpochRedeemAmounts epoch)))
public epochRedeemAmounts;
// Pending requests
mapping(ShareClassId scId => mapping(AssetId payoutAssetId => uint128 pending)) public pendingRedeem;
mapping(ShareClassId scId => mapping(AssetId depositAssetId => uint128 pending)) public pendingDeposit;
mapping(ShareClassId scId => mapping(AssetId payoutAssetId => mapping(bytes32 investor => UserOrder pending)))
public redeemRequest;
mapping(ShareClassId scId => mapping(AssetId depositAssetId => mapping(bytes32 investor => UserOrder pending)))
public depositRequest;
// Queued requests
mapping(ShareClassId scId => mapping(AssetId payoutAssetId => mapping(bytes32 investor => QueuedOrder queued)))
public queuedRedeemRequest;
mapping(ShareClassId scId => mapping(AssetId depositAssetId => mapping(bytes32 investor => QueuedOrder queued)))
public queuedDepositRequest;
// Force cancel request safeguards
mapping(ShareClassId scId => mapping(AssetId depositAssetId => mapping(bytes32 investor => bool cancelled))) public
allowForceDepositCancel;
mapping(ShareClassId scId => mapping(AssetId payoutAssetId => mapping(bytes32 investor => bool cancelled))) public
allowForceRedeemCancel;
constructor(IHubRegistry hubRegistry_, address deployer) Auth(deployer) {
hubRegistry = hubRegistry_;
}
//----------------------------------------------------------------------------------------------
// Administration
//----------------------------------------------------------------------------------------------
/// @inheritdoc IShareClassManager
function addShareClass(PoolId poolId, string calldata name, string calldata symbol, bytes32 salt)
external
auth
returns (ShareClassId scId_)
{
scId_ = previewNextShareClassId(poolId);
uint32 index = ++shareClassCount[poolId];
shareClassIds[poolId][scId_] = true;
_updateMetadata(scId_, name, symbol, salt);
emit AddShareClass(poolId, scId_, index, name, symbol, salt);
}
//----------------------------------------------------------------------------------------------
// Incoming requests
//----------------------------------------------------------------------------------------------
/// @inheritdoc IShareClassManager
function requestDeposit(PoolId poolId, ShareClassId scId_, uint128 amount, bytes32 investor, AssetId depositAssetId)
external
auth
{
require(exists(poolId, scId_), ShareClassNotFound());
// NOTE: Vaults ensure amount > 0
_updatePending(poolId, scId_, amount, true, investor, depositAssetId, RequestType.Deposit);
}
/// @inheritdoc IShareClassManager
function cancelDepositRequest(PoolId poolId, ShareClassId scId_, bytes32 investor, AssetId depositAssetId)
external
auth
returns (uint128 cancelledAssetAmount)
{
require(exists(poolId, scId_), ShareClassNotFound());
allowForceDepositCancel[scId_][depositAssetId][investor] = true;
uint128 cancellingAmount = depositRequest[scId_][depositAssetId][investor].pending;
return _updatePending(poolId, scId_, cancellingAmount, false, investor, depositAssetId, RequestType.Deposit);
}
/// @inheritdoc IShareClassManager
function requestRedeem(PoolId poolId, ShareClassId scId_, uint128 amount, bytes32 investor, AssetId payoutAssetId)
external
auth
{
require(exists(poolId, scId_), ShareClassNotFound());
// NOTE: Vaults ensure amount > 0
_updatePending(poolId, scId_, amount, true, investor, payoutAssetId, RequestType.Redeem);
}
/// @inheritdoc IShareClassManager
function cancelRedeemRequest(PoolId poolId, ShareClassId scId_, bytes32 investor, AssetId payoutAssetId)
external
auth
returns (uint128 cancelledShareAmount)
{
require(exists(poolId, scId_), ShareClassNotFound());
allowForceRedeemCancel[scId_][payoutAssetId][investor] = true;
uint128 cancellingAmount = redeemRequest[scId_][payoutAssetId][investor].pending;
return _updatePending(poolId, scId_, cancellingAmount, false, investor, payoutAssetId, RequestType.Redeem);
}
//----------------------------------------------------------------------------------------------
// Manager actions
//----------------------------------------------------------------------------------------------
/// @inheritdoc IShareClassManager
function approveDeposits(
PoolId poolId,
ShareClassId scId_,
AssetId depositAssetId,
uint32 nowDepositEpochId,
uint128 approvedAssetAmount,
D18 pricePoolPerAsset
) external auth returns (uint128 pendingAssetAmount, uint128 approvedPoolAmount) {
require(exists(poolId, scId_), ShareClassNotFound());
require(
nowDepositEpochId == nowDepositEpoch(scId_, depositAssetId),
EpochNotInSequence(nowDepositEpochId, nowDepositEpoch(scId_, depositAssetId))
);
// Limit in case approved > pending due to race condition of FM approval and async incoming requests
pendingAssetAmount = pendingDeposit[scId_][depositAssetId];
require(approvedAssetAmount <= pendingAssetAmount, InsufficientPending());
require(approvedAssetAmount > 0, ZeroApprovalAmount());
approvedPoolAmount = PricingLib.convertWithPrice(
approvedAssetAmount, hubRegistry.decimals(depositAssetId), hubRegistry.decimals(poolId), pricePoolPerAsset
);
// Update epoch data
EpochInvestAmounts storage epochAmounts = epochInvestAmounts[scId_][depositAssetId][nowDepositEpochId];
epochAmounts.approvedAssetAmount = approvedAssetAmount;
epochAmounts.approvedPoolAmount = approvedPoolAmount;
epochAmounts.pendingAssetAmount = pendingAssetAmount;
epochAmounts.pricePoolPerAsset = pricePoolPerAsset;
// Reduce pending
pendingDeposit[scId_][depositAssetId] -= approvedAssetAmount;
pendingAssetAmount -= approvedAssetAmount;
epochId[scId_][depositAssetId].deposit = nowDepositEpochId;
emit ApproveDeposits(
poolId,
scId_,
depositAssetId,
nowDepositEpochId,
approvedPoolAmount,
approvedAssetAmount,
pendingAssetAmount
);
}
/// @inheritdoc IShareClassManager
function approveRedeems(
PoolId poolId,
ShareClassId scId_,
AssetId payoutAssetId,
uint32 nowRedeemEpochId,
uint128 approvedShareAmount,
D18 pricePoolPerAsset
) external auth returns (uint128 pendingShareAmount) {
require(exists(poolId, scId_), ShareClassNotFound());
require(
nowRedeemEpochId == nowRedeemEpoch(scId_, payoutAssetId),
EpochNotInSequence(nowRedeemEpochId, nowRedeemEpoch(scId_, payoutAssetId))
);
// Limit in case approved > pending due to race condition of FM approval and async incoming requests
pendingShareAmount = pendingRedeem[scId_][payoutAssetId];
require(approvedShareAmount <= pendingShareAmount, InsufficientPending());
require(approvedShareAmount > 0, ZeroApprovalAmount());
// Update epoch data
EpochRedeemAmounts storage epochAmounts = epochRedeemAmounts[scId_][payoutAssetId][nowRedeemEpochId];
epochAmounts.approvedShareAmount = approvedShareAmount;
epochAmounts.pendingShareAmount = pendingShareAmount;
epochAmounts.pricePoolPerAsset = pricePoolPerAsset;
// Reduce pending
pendingRedeem[scId_][payoutAssetId] -= approvedShareAmount;
pendingShareAmount -= approvedShareAmount;
epochId[scId_][payoutAssetId].redeem = nowRedeemEpochId;
emit ApproveRedeems(poolId, scId_, payoutAssetId, nowRedeemEpochId, approvedShareAmount, pendingShareAmount);
}
/// @inheritdoc IShareClassManager
function issueShares(
PoolId poolId,
ShareClassId scId_,
AssetId depositAssetId,
uint32 nowIssueEpochId,
D18 navPoolPerShare
) external auth returns (uint128 issuedShareAmount, uint128 depositAssetAmount, uint128 depositPoolAmount) {
require(exists(poolId, scId_), ShareClassNotFound());
require(nowIssueEpochId <= epochId[scId_][depositAssetId].deposit, EpochNotFound());
require(
nowIssueEpochId == nowIssueEpoch(scId_, depositAssetId),
EpochNotInSequence(nowIssueEpochId, nowIssueEpoch(scId_, depositAssetId))
);
EpochInvestAmounts storage epochAmounts = epochInvestAmounts[scId_][depositAssetId][nowIssueEpochId];
epochAmounts.navPoolPerShare = navPoolPerShare;
issuedShareAmount = navPoolPerShare.isNotZero()
? PricingLib.assetToShareAmount(
epochAmounts.approvedAssetAmount,
hubRegistry.decimals(depositAssetId),
hubRegistry.decimals(poolId),
epochAmounts.pricePoolPerAsset,
navPoolPerShare,
MathLib.Rounding.Down
)
: 0;
epochAmounts.issuedAt = block.timestamp.toUint64();
epochId[scId_][depositAssetId].issue = nowIssueEpochId;
depositAssetAmount = epochAmounts.approvedAssetAmount;
depositPoolAmount = epochAmounts.approvedPoolAmount;
emit IssueShares(
poolId,
scId_,
depositAssetId,
nowIssueEpochId,
navPoolPerShare,
epochAmounts.pricePoolPerAsset.isNotZero()
? PricingLib.priceAssetPerShare(epochAmounts.navPoolPerShare, epochAmounts.pricePoolPerAsset)
: d18(0),
issuedShareAmount
);
}
/// @inheritdoc IShareClassManager
function revokeShares(
PoolId poolId,
ShareClassId scId_,
AssetId payoutAssetId,
uint32 nowRevokeEpochId,
D18 navPoolPerShare
) external auth returns (uint128 revokedShareAmount, uint128 payoutAssetAmount, uint128 payoutPoolAmount) {
require(exists(poolId, scId_), ShareClassNotFound());
require(nowRevokeEpochId <= epochId[scId_][payoutAssetId].redeem, EpochNotFound());
require(
nowRevokeEpochId == nowRevokeEpoch(scId_, payoutAssetId),
EpochNotInSequence(nowRevokeEpochId, nowRevokeEpoch(scId_, payoutAssetId))
);
EpochRedeemAmounts storage epochAmounts = epochRedeemAmounts[scId_][payoutAssetId][nowRevokeEpochId];
epochAmounts.navPoolPerShare = navPoolPerShare;
// NOTE: shares and pool currency have the same decimals - no conversion needed!
payoutPoolAmount = navPoolPerShare.mulUint128(epochAmounts.approvedShareAmount, MathLib.Rounding.Down);
payoutAssetAmount = epochAmounts.pricePoolPerAsset.isNotZero()
? PricingLib.shareToAssetAmount(
epochAmounts.approvedShareAmount,
hubRegistry.decimals(poolId),
hubRegistry.decimals(payoutAssetId),
epochAmounts.navPoolPerShare,
epochAmounts.pricePoolPerAsset,
MathLib.Rounding.Down
)
: 0;
revokedShareAmount = epochAmounts.approvedShareAmount;
epochAmounts.payoutAssetAmount = payoutAssetAmount;
epochAmounts.revokedAt = block.timestamp.toUint64();
epochId[scId_][payoutAssetId].revoke = nowRevokeEpochId;
emit RevokeShares(
poolId,
scId_,
payoutAssetId,
nowRevokeEpochId,
navPoolPerShare,
epochAmounts.pricePoolPerAsset.isNotZero()
? PricingLib.priceAssetPerShare(epochAmounts.navPoolPerShare, epochAmounts.pricePoolPerAsset)
: d18(0),
epochAmounts.approvedShareAmount,
payoutAssetAmount,
payoutPoolAmount
);
}
/// @inheritdoc IShareClassManager
function updateSharePrice(PoolId poolId, ShareClassId scId_, D18 navPoolPerShare) external auth {
require(exists(poolId, scId_), ShareClassNotFound());
ShareClassMetrics storage m = metrics[scId_];
m.navPerShare = navPoolPerShare;
emit UpdateShareClass(poolId, scId_, navPoolPerShare);
}
/// @inheritdoc IShareClassManager
function updateMetadata(PoolId poolId, ShareClassId scId_, string calldata name, string calldata symbol)
external
auth
{
require(exists(poolId, scId_), ShareClassNotFound());
_updateMetadata(scId_, name, symbol, bytes32(0));
emit UpdateMetadata(poolId, scId_, name, symbol);
}
/// @inheritdoc IShareClassManager
function updateShares(uint16 centrifugeId, PoolId poolId, ShareClassId scId_, uint128 amount, bool isIssuance)
external
auth
{
require(exists(poolId, scId_), ShareClassNotFound());
require(isIssuance || issuance[scId_][centrifugeId] >= amount, DecreaseMoreThanIssued());
uint128 newTotalIssuance =
isIssuance ? metrics[scId_].totalIssuance + amount : metrics[scId_].totalIssuance - amount;
metrics[scId_].totalIssuance = newTotalIssuance;
uint128 newIssuancePerNetwork =
isIssuance ? issuance[scId_][centrifugeId] + amount : issuance[scId_][centrifugeId] - amount;
issuance[scId_][centrifugeId] = newIssuancePerNetwork;
if (isIssuance) emit RemoteIssueShares(centrifugeId, poolId, scId_, amount);
else emit RemoteRevokeShares(centrifugeId, poolId, scId_, amount);
}
/// @inheritdoc IShareClassManager
function forceCancelDepositRequest(PoolId poolId, ShareClassId scId_, bytes32 investor, AssetId depositAssetId)
external
auth
returns (uint128 cancelledAssetAmount)
{
require(exists(poolId, scId_), ShareClassNotFound());
require(allowForceDepositCancel[scId_][depositAssetId][investor], CancellationInitializationRequired());
uint128 cancellingAmount = depositRequest[scId_][depositAssetId][investor].pending;
return _updatePending(poolId, scId_, cancellingAmount, false, investor, depositAssetId, RequestType.Deposit);
}
/// @inheritdoc IShareClassManager
function forceCancelRedeemRequest(PoolId poolId, ShareClassId scId_, bytes32 investor, AssetId payoutAssetId)
external
auth
returns (uint128 cancelledShareAmount)
{
require(exists(poolId, scId_), ShareClassNotFound());
require(allowForceRedeemCancel[scId_][payoutAssetId][investor], CancellationInitializationRequired());
uint128 cancellingAmount = redeemRequest[scId_][payoutAssetId][investor].pending;
return _updatePending(poolId, scId_, cancellingAmount, false, investor, payoutAssetId, RequestType.Redeem);
}
//----------------------------------------------------------------------------------------------
// Claiming methods
//----------------------------------------------------------------------------------------------
/// @inheritdoc IShareClassManager
function claimDeposit(PoolId poolId, ShareClassId scId_, bytes32 investor, AssetId depositAssetId)
public
auth
returns (
uint128 payoutShareAmount,
uint128 paymentAssetAmount,
uint128 cancelledAssetAmount,
bool canClaimAgain
)
{
require(exists(poolId, scId_), ShareClassNotFound());
UserOrder storage userOrder = depositRequest[scId_][depositAssetId][investor];
require(userOrder.pending > 0, NoOrderFound());
require(userOrder.lastUpdate <= epochId[scId_][depositAssetId].issue, IssuanceRequired());
canClaimAgain = userOrder.lastUpdate < epochId[scId_][depositAssetId].issue;
EpochInvestAmounts storage epochAmounts = epochInvestAmounts[scId_][depositAssetId][userOrder.lastUpdate];
paymentAssetAmount = epochAmounts.approvedAssetAmount == 0
? 0
: userOrder.pending.mulDiv(epochAmounts.approvedAssetAmount, epochAmounts.pendingAssetAmount).toUint128();
// NOTE: Due to precision loss, the sum of claimable user amounts is leq than the amount of minted share class
// tokens corresponding to the approved share amount (instead of equality). I.e., it is possible for an epoch to
// have an excess of a share class tokens which cannot be claimed by anyone.
if (paymentAssetAmount > 0) {
payoutShareAmount = epochAmounts.navPoolPerShare.isNotZero()
? PricingLib.assetToShareAmount(
paymentAssetAmount,
hubRegistry.decimals(depositAssetId),
hubRegistry.decimals(poolId),
epochAmounts.pricePoolPerAsset,
epochAmounts.navPoolPerShare,
MathLib.Rounding.Down
)
: 0;
userOrder.pending -= paymentAssetAmount;
}
emit ClaimDeposit(
poolId,
scId_,
userOrder.lastUpdate,
investor,
depositAssetId,
paymentAssetAmount,
userOrder.pending,
payoutShareAmount,
epochAmounts.issuedAt
);
// If there is nothing to claim anymore we can short circuit to the latest epoch
if (userOrder.pending == 0) {
// The current epoch is always one step ahead of the stored one
userOrder.lastUpdate = nowDepositEpoch(scId_, depositAssetId);
canClaimAgain = false;
} else {
userOrder.lastUpdate += 1;
}
// If user claimed up to latest approval epoch, move queued to pending
if (userOrder.lastUpdate == nowDepositEpoch(scId_, depositAssetId)) {
cancelledAssetAmount =
_postClaimUpdateQueued(poolId, scId_, investor, depositAssetId, userOrder, RequestType.Deposit);
}
}
/// @inheritdoc IShareClassManager
function claimRedeem(PoolId poolId, ShareClassId scId_, bytes32 investor, AssetId payoutAssetId)
public
auth
returns (
uint128 payoutAssetAmount,
uint128 paymentShareAmount,
uint128 cancelledShareAmount,
bool canClaimAgain
)
{
require(exists(poolId, scId_), ShareClassNotFound());
UserOrder storage userOrder = redeemRequest[scId_][payoutAssetId][investor];
require(userOrder.pending > 0, NoOrderFound());
require(userOrder.lastUpdate <= epochId[scId_][payoutAssetId].revoke, RevocationRequired());
canClaimAgain = userOrder.lastUpdate < epochId[scId_][payoutAssetId].revoke;
EpochRedeemAmounts storage epochAmounts = epochRedeemAmounts[scId_][payoutAssetId][userOrder.lastUpdate];
paymentShareAmount = epochAmounts.approvedShareAmount == 0
? 0
: userOrder.pending.mulDiv(epochAmounts.approvedShareAmount, epochAmounts.pendingShareAmount).toUint128();
// NOTE: Due to precision loss, the sum of claimable user amounts is leq than the amount of payout asset
// corresponding to the approved share class (instead of equality). I.e., it is possible for an epoch to
// have an excess of payout assets which cannot be claimed by anyone.
if (paymentShareAmount > 0) {
payoutAssetAmount = epochAmounts.pricePoolPerAsset.isNotZero()
? PricingLib.shareToAssetAmount(
paymentShareAmount,
hubRegistry.decimals(poolId),
hubRegistry.decimals(payoutAssetId),
epochAmounts.navPoolPerShare,
epochAmounts.pricePoolPerAsset,
MathLib.Rounding.Down
)
: 0;
userOrder.pending -= paymentShareAmount;
}
emit ClaimRedeem(
poolId,
scId_,
userOrder.lastUpdate,
investor,
payoutAssetId,
paymentShareAmount,
userOrder.pending,
payoutAssetAmount,
epochAmounts.revokedAt
);
// If there is nothing to claim anymore we can short circuit the in between epochs
if (userOrder.pending == 0) {
// The current epoch is always one step ahead of the stored one
userOrder.lastUpdate = nowRedeemEpoch(scId_, payoutAssetId);
canClaimAgain = false;
} else {
userOrder.lastUpdate += 1;
}
if (userOrder.lastUpdate == nowRedeemEpoch(scId_, payoutAssetId)) {
cancelledShareAmount =
_postClaimUpdateQueued(poolId, scId_, investor, payoutAssetId, userOrder, RequestType.Redeem);
}
}
//----------------------------------------------------------------------------------------------
// View methods
//----------------------------------------------------------------------------------------------
/// @inheritdoc IShareClassManager
function previewNextShareClassId(PoolId poolId) public view returns (ShareClassId scId) {
return newShareClassId(poolId, shareClassCount[poolId] + 1);
}
/// @inheritdoc IShareClassManager
function previewShareClassId(PoolId poolId, uint32 index) public pure returns (ShareClassId scId) {
return newShareClassId(poolId, index);
}
/// @inheritdoc IShareClassManager
function exists(PoolId poolId, ShareClassId scId_) public view returns (bool) {
return shareClassIds[poolId][scId_];
}
/// @inheritdoc IShareClassManager
function nowDepositEpoch(ShareClassId scId_, AssetId depositAssetId) public view returns (uint32) {
return epochId[scId_][depositAssetId].deposit + 1;
}
/// @inheritdoc IShareClassManager
function nowIssueEpoch(ShareClassId scId_, AssetId depositAssetId) public view returns (uint32) {
return epochId[scId_][depositAssetId].issue + 1;
}
/// @inheritdoc IShareClassManager
function nowRedeemEpoch(ShareClassId scId_, AssetId depositAssetId) public view returns (uint32) {
return epochId[scId_][depositAssetId].redeem + 1;
}
/// @inheritdoc IShareClassManager
function nowRevokeEpoch(ShareClassId scId_, AssetId depositAssetId) public view returns (uint32) {
return epochId[scId_][depositAssetId].revoke + 1;
}
/// @inheritdoc IShareClassManager
function maxDepositClaims(ShareClassId scId_, bytes32 investor, AssetId depositAssetId)
public
view
returns (uint32)
{
return _maxClaims(depositRequest[scId_][depositAssetId][investor], epochId[scId_][depositAssetId].deposit);
}
/// @inheritdoc IShareClassManager
function maxRedeemClaims(ShareClassId scId_, bytes32 investor, AssetId payoutAssetId)
public
view
returns (uint32)
{
return _maxClaims(redeemRequest[scId_][payoutAssetId][investor], epochId[scId_][payoutAssetId].redeem);
}
function _maxClaims(UserOrder memory userOrder, uint32 lastEpoch) internal pure returns (uint32) {
// User order either not set or not processed
if (userOrder.pending == 0 || userOrder.lastUpdate > lastEpoch) {
return 0;
}
return lastEpoch - userOrder.lastUpdate + 1;
}
//----------------------------------------------------------------------------------------------
// Internal methods
//----------------------------------------------------------------------------------------------
function _updateMetadata(ShareClassId scId_, string calldata name, string calldata symbol, bytes32 salt) internal {
uint256 nameLen = bytes(name).length;
require(nameLen > 0 && nameLen <= 128, InvalidMetadataName());
uint256 symbolLen = bytes(symbol).length;
require(symbolLen > 0 && symbolLen <= 32, InvalidMetadataSymbol());
ShareClassMetadata storage meta = metadata[scId_];
// Ensure that the salt is not being updated or is being set for the first time
require(
(salt == bytes32(0) && meta.salt != bytes32(0)) || (salt != bytes32(0) && meta.salt == bytes32(0)),
InvalidSalt()
);
if (salt != bytes32(0) && meta.salt == bytes32(0)) {
require(!salts[salt], AlreadyUsedSalt());
salts[salt] = true;
meta.salt = salt;
}
meta.name = name;
meta.symbol = symbol;
}
function _postClaimUpdateQueued(
PoolId poolId,
ShareClassId scId_,
bytes32 investor,
AssetId assetId,
UserOrder storage userOrder,
RequestType requestType
) internal returns (uint128 cancelledAmount) {
QueuedOrder storage queued = requestType == RequestType.Deposit
? queuedDepositRequest[scId_][assetId][investor]
: queuedRedeemRequest[scId_][assetId][investor];
// Increment pending by queued or cancel everything
uint128 updatePendingAmount = queued.isCancelling ? userOrder.pending : queued.amount;
if (queued.isCancelling) {
cancelledAmount = userOrder.pending + queued.amount;
userOrder.pending = 0;
} else {
userOrder.pending += queued.amount;
}
if (requestType == RequestType.Deposit) {
_updatePendingDeposit(
poolId,
scId_,
updatePendingAmount,
!queued.isCancelling,
investor,
assetId,
userOrder,
QueuedOrder(false, 0)
);
} else {
_updatePendingRedeem(
poolId,
scId_,
updatePendingAmount,
!queued.isCancelling,
investor,
assetId,
userOrder,
QueuedOrder(false, 0)
);
}
// Clear queued
queued.isCancelling = false;
queued.amount = 0;
}
/// @notice Updates the amount of a deposit or redeem request.
///
/// @param poolId Identifier of the pool
/// @param scId_ Identifier of the share class
/// @param amount Amount which is updated
/// @param isIncrement Whether the amount is positive (additional request) or negative (cancellation)
/// @param investor Address of the entity which is depositing
/// @param assetId Identifier of the asset which the investor either used as deposit or wants to redeem to
/// @param requestType Flag indicating whether the request is a deposit or redeem request
/// @return cancelledAmount Pending amount which was cancelled
function _updatePending(
PoolId poolId,
ShareClassId scId_,
uint128 amount,
bool isIncrement,
bytes32 investor,
AssetId assetId,
RequestType requestType
) internal returns (uint128 cancelledAmount) {
UserOrder storage userOrder = requestType == RequestType.Deposit
? depositRequest[scId_][assetId][investor]
: redeemRequest[scId_][assetId][investor];
QueuedOrder storage queued = requestType == RequestType.Deposit
? queuedDepositRequest[scId_][assetId][investor]
: queuedRedeemRequest[scId_][assetId][investor];
// We must only update either queued or pending
if (_updateQueued(poolId, scId_, amount, isIncrement, investor, assetId, userOrder, queued, requestType)) {
return 0;
}
cancelledAmount = isIncrement ? 0 : amount;
// NOTE: If we decrease the pending, we decrease usually by the full amount
// We keep subtraction of amount over setting to zero on purpose to not limit future higher level logic
userOrder.pending = isIncrement ? userOrder.pending + amount : userOrder.pending - amount;
userOrder.lastUpdate =
requestType == RequestType.Deposit ? nowDepositEpoch(scId_, assetId) : nowRedeemEpoch(scId_, assetId);
if (requestType == RequestType.Deposit) {
_updatePendingDeposit(poolId, scId_, amount, isIncrement, investor, assetId, userOrder, queued);
} else {
_updatePendingRedeem(poolId, scId_, amount, isIncrement, investor, assetId, userOrder, queued);
}
}
/// @notice Checks whether the pending amount can be updated. If not, it updates the queued amount.
///
/// @param poolId Identifier of the pool
/// @param scId_ Identifier of the share class
/// @param amount Amount which is updated
/// @param isIncrement Whether the amount is positive (additional request) or negative (cancellation)
/// @param investor Address of the entity which is depositing
/// @param assetId Identifier of the asset which the investor either used as deposit or wants to redeem to
/// @param userOrder User order storage for the deposit or redeem request
/// @param requestType Flag indicating whether the request is a deposit or redeem request
/// @return skipPendingUpdate Flag indicating whether the pending amount can be updated which is true if the user
/// does not need to claim
function _updateQueued(
PoolId poolId,
ShareClassId scId_,
uint128 amount,
bool isIncrement,
bytes32 investor,
AssetId assetId,
UserOrder storage userOrder,
QueuedOrder storage queued,
RequestType requestType
) internal returns (bool skipPendingUpdate) {
uint32 currentEpoch =
requestType == RequestType.Deposit ? nowDepositEpoch(scId_, assetId) : nowRedeemEpoch(scId_, assetId);
// Short circuit if user can mutate pending, i.e. last update happened after latest approval or is first update
if (_canMutatePending(userOrder, currentEpoch)) {
return false;
}
// Block increasing queued amount if cancelling is already queued
// NOTE: Can only happen due to race condition as Vaults blocks requests if cancellation is in progress
require(!(queued.isCancelling && amount > 0), CancellationQueued());
if (!isIncrement) {
queued.isCancelling = true;
} else {
queued.amount += amount;
}
if (requestType == RequestType.Deposit) {
uint128 pendingTotal = pendingDeposit[scId_][assetId];
emit UpdateDepositRequest(
poolId,
scId_,
assetId,
currentEpoch,
investor,
userOrder.pending,
pendingTotal,
queued.amount,
queued.isCancelling
);
} else {
uint128 pendingTotal = pendingRedeem[scId_][assetId];
emit UpdateRedeemRequest(
poolId,
scId_,
assetId,
currentEpoch,
investor,
userOrder.pending,
pendingTotal,
queued.amount,
queued.isCancelling
);
}
return true;
}
function _updatePendingDeposit(
PoolId poolId,
ShareClassId scId_,
uint128 amount,
bool isIncrement,
bytes32 investor,
AssetId assetId,
UserOrder storage userOrder,
QueuedOrder memory queued
) internal {
uint128 pendingTotal = pendingDeposit[scId_][assetId];
pendingTotal = isIncrement ? pendingTotal + amount : pendingTotal - amount;
pendingDeposit[scId_][assetId] = pendingTotal;
emit UpdateDepositRequest(
poolId,
scId_,
assetId,
nowDepositEpoch(scId_, assetId),
investor,
userOrder.pending,
pendingTotal,
queued.amount,
queued.isCancelling
);
}
function _updatePendingRedeem(
PoolId poolId,
ShareClassId scId_,
uint128 amount,
bool isIncrement,
bytes32 investor,
AssetId assetId,
UserOrder storage userOrder,
QueuedOrder memory queued
) internal {
uint128 pendingTotal = pendingRedeem[scId_][assetId];
pendingTotal = isIncrement ? pendingTotal + amount : pendingTotal - amount;
pendingRedeem[scId_][assetId] = pendingTotal;
emit UpdateRedeemRequest(
poolId,
scId_,
assetId,
nowRedeemEpoch(scId_, assetId),
investor,
userOrder.pending,
pendingTotal,
queued.amount,
queued.isCancelling
);
}
/// @dev A user cannot mutate their pending amount at all times because it affects the total pending amount. It is
/// restricted to the following three conditions:
/// 1. It's the first epoch (currentEpoch <= 1), which implies userOrder.lastUpdate == 0
/// 2. User has no pending amount (userOrder.pending == 0)
/// 3. User's last update is not behind the current epoch (userOrder.lastUpdate >= currentEpoch)
function _canMutatePending(UserOrder memory userOrder, uint32 currentEpoch) internal pure returns (bool) {
return currentEpoch <= 1 || userOrder.pending == 0 || userOrder.lastUpdate >= currentEpoch;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.28;
import {IAuth} from "src/misc/interfaces/IAuth.sol";
/// @title Auth
/// @notice Simple authentication pattern
/// @author Based on code from https://github.com/makerdao/dss
abstract contract Auth is IAuth {
/// @inheritdoc IAuth
mapping(address => uint256) public wards;
constructor(address initialWard) {
wards[initialWard] = 1;
emit Rely(initialWard);
}
/// @dev Check if the msg.sender has permissions
modifier auth() {
require(wards[msg.sender] == 1, NotAuthorized());
_;
}
/// @inheritdoc IAuth
function rely(address user) public auth {
wards[user] = 1;
emit Rely(user);
}
/// @inheritdoc IAuth
function deny(address user) public auth {
wards[user] = 0;
emit Deny(user);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.28;
// Small library to handle fixed point number operations with 18 decimals with static typing support.
import {MathLib} from "src/misc/libraries/MathLib.sol";
type D18 is uint128;
using MathLib for uint256;
/// @dev add two D18 types
function add(D18 d1, D18 d2) pure returns (D18) {
return D18.wrap(D18.unwrap(d1) + D18.unwrap(d2));
}
/// @dev substract two D18 types
function sub(D18 d1, D18 d2) pure returns (D18) {
return D18.wrap(D18.unwrap(d1) - D18.unwrap(d2));
}
/// @dev Divides one D18 by another one while retaining precision:
/// - nominator (decimal): 50e18
/// - denominator (decimal): 2e19
/// - result (decimal): 25e17
function divD18(D18 d1, D18 d2) pure returns (D18) {
return D18.wrap(MathLib.mulDiv(D18.unwrap(d1), 1e18, D18.unwrap(d2)).toUint128());
}
/// @dev Multiplies one D18 with another one while retaining precision:
/// - value1 (decimal): 50e18
/// - value2 (decimal): 2e19
/// - result (decimal): 100e19
function mulD18(D18 d1, D18 d2) pure returns (D18) {
return D18.wrap(MathLib.mulDiv(D18.unwrap(d1), D18.unwrap(d2), 1e18).toUint128());
}
/// @dev Returns the reciprocal of a D18 decimal, i.e. 1 / d.
/// Example: if d = 2.0 (2e18 internally), reciprocal(d) = 0.5 (5e17 internally).
function reciprocal(D18 d) pure returns (D18) {
uint128 val = D18.unwrap(d);
require(val != 0, "D18/division-by-zero");
return d18(1e18, val);
}
/// @dev Multiplies a decimal by an integer. i.e:
/// - d (decimal): 1_500_000_000_000_000_000
/// - value (integer): 4_000_000_000_000_000_000
/// - result (integer): 6_000_000_000_000_000_000
function mulUint128(D18 d, uint128 value, MathLib.Rounding rounding) pure returns (uint128) {
return MathLib.mulDiv(D18.unwrap(d), value, 1e18, rounding).toUint128();
}
/// @dev Multiplies a decimal by an integer. i.e:
/// - d (decimal): 1_500_000_000_000_000_000
/// - value (integer): 4_000_000_000_000_000_000
/// - result (integer): 6_000_000_000_000_000_000
function mulUint256(D18 d, uint256 value, MathLib.Rounding rounding) pure returns (uint256) {
return MathLib.mulDiv(D18.unwrap(d), value, 1e18, rounding);
}
/// @dev Divides an integer by a decimal, i.e.
/// @dev Same as mulDiv for integers, i.e:
/// - d (decimal): 2_000_000_000_000_000_000
/// - value (integer): 100_000_000_000_000_000_000
/// - result (integer): 50_000_000_000_000_000_000
function reciprocalMulUint128(D18 d, uint128 value, MathLib.Rounding rounding) pure returns (uint128) {
return MathLib.mulDiv(value, 1e18, d.raw(), rounding).toUint128();
}
/// @dev Divides an integer by a decimal, i.e.
/// @dev Same as mulDiv for integers, i.e:
/// - d (decimal): 2_000_000_000_000_000_000
/// - value (integer): 100_000_000_000_000_000_000
/// - result (integer): 50_000_000_000_000_000_000
function reciprocalMulUint256(D18 d, uint256 value, MathLib.Rounding rounding) pure returns (uint256) {
return MathLib.mulDiv(value, 1e18, d.raw(), rounding);
}
/// @dev Easy way to construct a decimal number
function d18(uint128 value) pure returns (D18) {
return D18.wrap(value);
}
/// @dev Easy way to construct a decimal number
function d18(uint128 num, uint128 den) pure returns (D18) {
return D18.wrap(MathLib.mulDiv(num, 1e18, den).toUint128());
}
function eq(D18 a, D18 b) pure returns (bool) {
return D18.unwrap(a) == D18.unwrap(b);
}
function isZero(D18 a) pure returns (bool) {
return D18.unwrap(a) == 0;
}
function isNotZero(D18 a) pure returns (bool) {
return D18.unwrap(a) != 0;
}
function raw(D18 d) pure returns (uint128) {
return D18.unwrap(d);
}
using {
add as +,
sub as -,
divD18 as /,
eq,
mulD18 as *,
mulUint128,
mulUint256,
reciprocalMulUint128,
reciprocalMulUint256,
reciprocal,
raw,
isZero,
isNotZero
} for D18 global;// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.28;
/// @title CastLib
library CastLib {
function toAddressLeftPadded(bytes32 addr) internal pure returns (address) {
require(bytes12(addr) == 0, "First 12 bytes should be zero");
return address(uint160(uint256(addr)));
}
function toBytes32LeftPadded(address addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(addr)));
}
function toAddress(bytes32 addr) internal pure returns (address) {
require(uint96(uint256(addr)) == 0, "Input should be 20 bytes");
return address(bytes20(addr));
}
function toBytes32(address addr) internal pure returns (bytes32) {
return bytes32(bytes20(addr));
}
/// @dev Adds zero padding
function toBytes32(string memory source) internal pure returns (bytes32) {
return bytes32(bytes(source));
}
/// @dev Removes zero padding
function bytes128ToString(bytes memory _bytes128) internal pure returns (string memory) {
require(_bytes128.length == 128, "Input should be 128 bytes");
uint8 i = 0;
while (i < 128 && _bytes128[i] != 0) {
i++;
}
bytes memory bytesArray = new bytes(i);
for (uint8 j; j < i; j++) {
bytesArray[j] = _bytes128[j];
}
return string(bytesArray);
}
function toString(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);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.28;
library MathLib {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
error MulDiv_Overflow();
error Uint8_Overflow();
error Uint32_Overflow();
error Uint64_Overflow();
error Uint128_Overflow();
error Int128_Overflow();
uint256 public constant One27 = 10 ** 27;
/// @notice Returns x^n with rounding precision of base
///
/// @dev Source: https://github.com/makerdao/dss/blob/fa4f6630afb0624d04a003e920b0d71a00331d98/src/jug.sol#L62
///
/// @param x The base value which should be exponentiated
/// @param n The exponent
/// @param base The scaling base, typically used for fix-point calculations
function rpow(uint256 x, uint256 n, uint256 base) public pure returns (uint256 z) {
assembly {
switch x
case 0 {
switch n
case 0 { z := base }
default { z := 0 }
}
default {
switch mod(n, 2)
case 0 { z := base }
default { z := x }
let half := div(base, 2) // for rounding.
for { n := div(n, 2) } n { n := div(n, 2) } {
let xx := mul(x, x)
if iszero(eq(div(xx, x), x)) { revert(0, 0) }
let xxRound := add(xx, half)
if lt(xxRound, xx) { revert(0, 0) }
x := div(xxRound, base)
if mod(n, 2) {
let zx := mul(z, x)
if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0, 0) }
let zxRound := add(zx, half)
if lt(zxRound, zx) { revert(0, 0) }
z := div(zxRound, base)
}
}
}
}
}
/// @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.
// slither-disable-start divide-before-multiply
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) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, MulDiv_Overflow());
///////////////////////////////////////////////
// 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;
}
}
// slither-disable-end divide-before-multiply
/// @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;
}
/// @notice Safe type conversion from uint256 to uint8.
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, Uint8_Overflow());
return uint8(value);
}
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, Uint32_Overflow());
return uint32(value);
}
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, Uint64_Overflow());
return uint64(value);
}
/// @notice Safe type conversion from uint256 to uint128.
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, Uint128_Overflow());
return uint128(value);
}
/// @notice Returns the smallest of two numbers.
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? b : a;
}
/// @notice Returns the largest of two numbers.
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.28;
/// @title Bytes Lib
/// @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
/// The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
/// @author Modified from Solidity Bytes Arrays Utils v0.8.0
library BytesLib {
error SliceOverflow();
error SliceOutOfBounds();
function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {
unchecked {
require(_length + 31 >= _length, SliceOverflow());
}
require(_bytes.length >= _start + _length, SliceOutOfBounds());
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// The first word of the slice result is potentially a partial
// word read from the original array. To read it, we calculate
// the length of that partial word and start copying that many
// bytes into the array. The first word we copy will start with
// data we don't care about, but the last `lengthmod` bytes will
// land at the beginning of the contents of the new array. When
// we're done copying, we overwrite the full first word with
// the actual length of the slice.
let lengthmod := and(_length, 31)
// The multiplication in the next line is necessary
// because when slicing multiples of 32 bytes (lengthmod == 0)
// the following copy loop was copying the origin's length
// and then ending prematurely not copying everything it should.
let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
let end := add(mc, _length)
for {
// The multiplication in the next line has the same exact purpose
// as the one above.
let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} { mstore(mc, mload(cc)) }
mstore(tempBytes, _length)
//update free-memory pointer
//allocating the array padded to 32 bytes like the compiler does now
mstore(0x40, and(add(mc, 31), not(31)))
}
//if we want a zero-length slice let's just return a zero-length array
default {
tempBytes := mload(0x40)
//zero out the 32 bytes slice we are about to return
//we need to do it because Solidity does not garbage collect
mstore(tempBytes, 0)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
function sliceZeroPadded(bytes memory _bytes, uint256 _start, uint256 _length)
internal
pure
returns (bytes memory)
{
bool needsPad = _bytes.length < _start + _length;
if (!needsPad) return slice(_bytes, _start, _length);
bytes memory slice_ = slice(_bytes, _start, _bytes.length - _start);
bytes memory padding = new bytes(_length + _start - _bytes.length);
return bytes.concat(slice_, padding);
}
function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
require(_bytes.length >= _start + 20, SliceOutOfBounds());
address tempAddress;
assembly {
tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
}
return tempAddress;
}
function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
require(_bytes.length >= _start + 1, SliceOutOfBounds());
uint8 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x1), _start))
}
return tempUint;
}
function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
require(_bytes.length >= _start + 2, SliceOutOfBounds());
uint16 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x2), _start))
}
return tempUint;
}
function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
require(_bytes.length >= _start + 4, SliceOutOfBounds());
uint32 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x4), _start))
}
return tempUint;
}
function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
require(_bytes.length >= _start + 8, SliceOutOfBounds());
uint64 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x8), _start))
}
return tempUint;
}
function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
require(_bytes.length >= _start + 16, SliceOutOfBounds());
uint128 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x10), _start))
}
return tempUint;
}
function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
require(_bytes.length >= _start + 32, SliceOutOfBounds());
uint256 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x20), _start))
}
return tempUint;
}
function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
require(_bytes.length >= _start + 32, SliceOutOfBounds());
bytes32 tempBytes32;
assembly {
tempBytes32 := mload(add(add(_bytes, 0x20), _start))
}
return tempBytes32;
}
function toBytes16(bytes memory _bytes, uint256 _start) internal pure returns (bytes16) {
require(_bytes.length >= _start + 16, SliceOutOfBounds());
bytes16 tempBytes16;
assembly {
tempBytes16 := mload(add(add(_bytes, 0x20), _start))
}
return tempBytes16;
}
function toBool(bytes memory _bytes, uint256 _start) internal pure returns (bool) {
require(_bytes.length > _start, SliceOutOfBounds());
return _bytes[_start] != 0;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import {MathLib} from "src/misc/libraries/MathLib.sol";
using MathLib for uint256;
type PoolId is uint64;
function centrifugeId(PoolId poolId) pure returns (uint16) {
return uint16(PoolId.unwrap(poolId) >> 48);
}
function newPoolId(uint16 centrifugeId_, uint48 localPoolId) pure returns (PoolId) {
return PoolId.wrap((uint64(centrifugeId_) << 48) | uint64(localPoolId));
}
function isNull(PoolId poolId) pure returns (bool) {
return PoolId.unwrap(poolId) == 0;
}
function isEqual(PoolId a, PoolId b) pure returns (bool) {
return PoolId.unwrap(a) == PoolId.unwrap(b);
}
function raw(PoolId poolId) pure returns (uint64) {
return PoolId.unwrap(poolId);
}
using {centrifugeId, isNull, raw, isEqual as ==} for PoolId global;// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
/// @dev Composite Id of the centrifugeId (uint16) where the asset resides
/// and a local counter (uint64) that is part of the contract that registers the asset.
type AssetId is uint128;
function isNull(AssetId assetId) pure returns (bool) {
return AssetId.unwrap(assetId) == 0;
}
function raw(AssetId assetId) pure returns (uint128) {
return AssetId.unwrap(assetId);
}
function centrifugeId(AssetId assetId) pure returns (uint16) {
return uint16(AssetId.unwrap(assetId) >> 112);
}
function newAssetId(uint16 centrifugeId_, uint64 counter) pure returns (AssetId) {
return AssetId.wrap((uint128(centrifugeId_) << 112) + counter);
}
function newAssetId(uint32 isoCode) pure returns (AssetId) {
return AssetId.wrap(isoCode);
}
function eq(AssetId a, AssetId b) pure returns (bool) {
return a.raw() == b.raw();
}
using {isNull, raw, centrifugeId, eq} for AssetId global;// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import {D18, d18} from "src/misc/types/D18.sol";
import {MathLib} from "src/misc/libraries/MathLib.sol";
import {IERC20Metadata} from "src/misc/interfaces/IERC20.sol";
import {IERC6909MetadataExt} from "src/misc/interfaces/IERC6909.sol";
import {PricingLib} from "src/common/libraries/PricingLib.sol";
library PricingLib {
using MathLib for *;
/// @dev Prices are fixed-point integers with 18 decimals
uint8 internal constant PRICE_DECIMALS = 18;
//----------------------------------------------------------------------------------------------
// View methods
//----------------------------------------------------------------------------------------------
/// @dev Converts the given asset amount to share amount. Returned value is in share decimals.
/// @dev Assumes handling of zero denominator price (priceAssetPerShare_) by consumer.
///
/// NOTE: MUST ONLY be used in AsyncRequestManager which rely on priceAssetPerShare that is derived from
/// Fulfilled* message amounts. Any other codepath must use the variant with pricePoolPerAsset
/// and pricePoolPerShare
function assetToShareAmount(
address shareToken,
address asset,
uint256 tokenId,
uint128 assetAmount,
D18 priceAssetPerShare_,
MathLib.Rounding rounding
) internal view returns (uint128 shares) {
if (assetAmount == 0) {
return 0;
}
uint8 assetDecimals = _getAssetDecimals(asset, tokenId);
uint8 shareDecimals = IERC20Metadata(shareToken).decimals();
return PricingLib.convertWithReciprocalPrice(
assetAmount, assetDecimals, shareDecimals, priceAssetPerShare_, rounding
).toUint128();
}
/// @dev Converts the given asset amount to share amount. Returned value is in share decimals.
/// @dev Assumes handling of zero denominator price (pricePoolPerShare) by consumer.
function assetToShareAmount(
address shareToken,
address asset,
uint256 tokenId,
uint128 assetAmount,
D18 pricePoolPerAsset,
D18 pricePoolPerShare,
MathLib.Rounding rounding
) internal view returns (uint128 shares) {
if (assetAmount == 0 || pricePoolPerAsset.isZero()) {
return 0;
}
uint8 assetDecimals = _getAssetDecimals(asset, tokenId);
uint8 shareDecimals = IERC20Metadata(shareToken).decimals();
return PricingLib.assetToShareAmount(
assetAmount, assetDecimals, shareDecimals, pricePoolPerAsset, pricePoolPerShare, rounding
).toUint128();
}
/// @dev Converts the given share amount to asset amount. Returned value is in share decimals.
///
/// NOTE: MUST ONLY be used in AsyncRequestManager which rely on priceAssetPerShare that is derived from
/// Fulfilled* message amounts. Any other codepath must use the variant with pricePoolPerAsset and
/// pricePoolPerShare
function shareToAssetAmount(
address shareToken,
uint128 shareAmount,
address asset,
uint256 tokenId,
D18 priceAssetPerShare_,
MathLib.Rounding rounding
) internal view returns (uint128 assets) {
if (shareAmount == 0 || priceAssetPerShare_.isZero()) {
return 0;
}
uint8 assetDecimals = _getAssetDecimals(asset, tokenId);
uint8 shareDecimals = IERC20Metadata(shareToken).decimals();
return PricingLib.convertWithPrice(shareAmount, shareDecimals, assetDecimals, priceAssetPerShare_, rounding);
}
/// @dev Converts the given share amount to asset amount. Returned value is in share decimals.
/// @dev Assumes handling of zero denominator price (pricePoolPerAsset) by consumer.
function shareToAssetAmount(
address shareToken,
uint128 shareAmount,
address asset,
uint256 tokenId,
D18 pricePoolPerShare,
D18 pricePoolPerAsset,
MathLib.Rounding rounding
) internal view returns (uint128 shares) {
if (shareAmount == 0 || pricePoolPerShare.isZero()) {
return 0;
}
uint8 assetDecimals = _getAssetDecimals(asset, tokenId);
uint8 shareDecimals = IERC20Metadata(shareToken).decimals();
// NOTE: Pool and share denomination are always equal by design
return PricingLib.shareToAssetAmount(
shareAmount, shareDecimals, assetDecimals, pricePoolPerShare, pricePoolPerAsset, rounding
).toUint128();
}
/// @dev Calculates the asset price per share returns the value in price decimals
/// Denominated in ASSET_UNIT/SHARE_UNIT
/// @dev Assumes handling of zero denominator (shares == 0) by consumer.
function calculatePriceAssetPerShare(
address shareToken,
uint128 shares,
address asset,
uint256 tokenId,
uint128 assets,
MathLib.Rounding rounding
) internal view returns (D18 priceAssetPerShare_) {
if (assets == 0) {
return d18(0);
}
uint8 assetDecimals = _getAssetDecimals(asset, tokenId);
uint8 shareDecimals = IERC20Metadata(shareToken).decimals();
// NOTE: More precise than utilizing D18
return d18(
_toPriceDecimals(assets, assetDecimals).mulDiv(
10 ** PRICE_DECIMALS, _toPriceDecimals(shares, shareDecimals), rounding
).toUint128()
);
}
//----------------------------------------------------------------------------------------------
// Pure methods
//----------------------------------------------------------------------------------------------
/// @dev Converts an amount using decimals and price with implicit rounding down
function convertWithPrice(uint256 baseAmount, uint8 baseDecimals, uint8 quoteDecimals, D18 priceQuotePerBase)
internal
pure
returns (uint128 quoteAmount)
{
return convertWithPrice(baseAmount, baseDecimals, quoteDecimals, priceQuotePerBase, MathLib.Rounding.Down);
}
/// @dev Converts an amount using decimals and price with explicit rounding.
function convertWithPrice(
uint256 baseAmount,
uint8 baseDecimals,
uint8 quoteDecimals,
D18 priceQuotePerBase,
MathLib.Rounding rounding
) internal pure returns (uint128 quoteAmount) {
if (baseDecimals == quoteDecimals) {
return priceQuotePerBase.mulUint256(baseAmount, rounding).toUint128();
}
return MathLib.mulDiv(
priceQuotePerBase.raw(), baseAmount * 10 ** quoteDecimals, 10 ** (baseDecimals + PRICE_DECIMALS), rounding
) // cancel out exponentiation from D18 multiplication
.toUint128();
}
/// @dev Converts an amount using decimals and reciprocal price.
/// @dev Assumes handling of zero denominator price (priceBasePerQuote) by consumer.
///
/// NOTE: More precise than convertWithPrice(,,,price.reciprocal,)
function convertWithReciprocalPrice(
uint256 baseAmount,
uint8 baseDecimals,
uint8 quoteDecimals,
D18 priceBasePerQuote,
MathLib.Rounding rounding
) internal pure returns (uint128 quoteAmount) {
require(priceBasePerQuote.isNotZero(), "PricingLib/division-by-zero");
if (baseDecimals == quoteDecimals) {
return priceBasePerQuote.reciprocalMulUint256(baseAmount, rounding).toUint128();
}
return MathLib.mulDiv(
10 ** quoteDecimals * baseAmount,
10 ** PRICE_DECIMALS,
10 ** baseDecimals * priceBasePerQuote.raw(),
rounding
).toUint128();
}
/// @dev Converts an amount using decimals and two prices.
/// @dev Assumes handling of zero denominator price (priceDenominator) by consumer.
///
/// NOTE: More precise than custom math with one price and convertWith{Reciprocal}Price for the other
function convertWithPrices(
uint256 baseAmount,
uint8 baseDecimals,
uint8 quoteDecimals,
D18 priceNumerator,
D18 priceDenominator,
MathLib.Rounding rounding
) internal pure returns (uint128 quoteAmount) {
require(priceDenominator.isNotZero(), "PricingLib/division-by-zero");
return MathLib.mulDiv(
priceNumerator.raw(),
10 ** quoteDecimals * baseAmount,
10 ** baseDecimals * priceDenominator.raw(),
rounding
).toUint128();
}
/// @dev Converts asset amount to share amount.
/// @dev Assumes handling of zero denominator price (pricePoolPerShare) by consumer.
///
/// NOTE: Pool and share denomination are always equal by design
function assetToShareAmount(
uint256 assetAmount,
uint8 assetDecimals,
uint8 shareDecimals,
D18 pricePoolPerAsset,
D18 pricePoolPerShare,
MathLib.Rounding rounding
) internal pure returns (uint128 shareAmount) {
return
convertWithPrices(assetAmount, assetDecimals, shareDecimals, pricePoolPerAsset, pricePoolPerShare, rounding);
}
/// @dev Converts share amount to asset asset amount.
/// @dev Assumes handling of zero denominator price (pricePoolPerAsset) by consumer.
///
/// NOTE: Pool and share denomination are always equal by design
function shareToAssetAmount(
uint256 shareAmount,
uint8 shareDecimals,
uint8 assetDecimals,
D18 pricePoolPerShare,
D18 pricePoolPerAsset,
MathLib.Rounding rounding
) internal pure returns (uint128 assetAmount) {
return
convertWithPrices(shareAmount, shareDecimals, assetDecimals, pricePoolPerShare, pricePoolPerAsset, rounding);
}
/// @dev Converts pool amount to asset amount.
/// @dev Assumes handling of zero denominator price (pricePoolPerAsset) by consumer.
function poolToAssetAmount(
uint256 poolAmount,
uint8 poolDecimals,
uint8 assetDecimals,
D18 pricePoolPerAsset,
MathLib.Rounding rounding
) internal pure returns (uint128 assetAmount) {
return convertWithReciprocalPrice(poolAmount, poolDecimals, assetDecimals, pricePoolPerAsset, rounding);
}
/// @dev Converts asset amount to pool amount.
function assetToPoolAmount(
uint128 assetAmount,
uint8 assetDecimals,
uint8 poolDecimals,
D18 pricePoolPerAsset,
MathLib.Rounding rounding
) internal pure returns (uint128 poolAmount) {
return convertWithPrice(assetAmount, assetDecimals, poolDecimals, pricePoolPerAsset, rounding);
}
/// @dev Returns the asset price per share denominated in ASSET_UNIT/SHARE_UNIT
/// @dev Assumes handling of zero denominator price (pricePoolPerAsset) by consumer.
///
/// NOTE: Should never be used for calculating amounts due to precision loss. Instead, please refer to
/// conversion relying on pricePoolPerShare and pricePoolPerAsset.
function priceAssetPerShare(D18 pricePoolPerShare, D18 pricePoolPerAsset)
internal
pure
returns (D18 priceAssetPerShare_)
{
return pricePoolPerShare / pricePoolPerAsset;
}
//----------------------------------------------------------------------------------------------
// Private methods
//----------------------------------------------------------------------------------------------
/// @dev Returns the asset decimals
function _getAssetDecimals(address asset, uint256 tokenId) private view returns (uint8 assetDecimals) {
return tokenId == 0 ? IERC20Metadata(asset).decimals() : IERC6909MetadataExt(asset).decimals(tokenId);
}
/// @dev When converting assets to shares using the price, all values are normalized to PRICE_DECIMALS
/// NOTE: We require all assets to have 2 <= decimals <= 18, see `Spoke.registerAsset`
function _toPriceDecimals(uint128 _value, uint8 decimals) private pure returns (uint256) {
if (PRICE_DECIMALS == decimals) return uint256(_value);
return uint256(_value) * 10 ** (PRICE_DECIMALS - decimals);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import {PoolId} from "src/common/types/PoolId.sol";
type ShareClassId is bytes16;
function isNull(ShareClassId scId) pure returns (bool) {
return ShareClassId.unwrap(scId) == 0;
}
function equals(ShareClassId left, ShareClassId right) pure returns (bool) {
return ShareClassId.unwrap(left) == ShareClassId.unwrap(right);
}
function raw(ShareClassId scId) pure returns (bytes16) {
return ShareClassId.unwrap(scId);
}
function newShareClassId(PoolId poolId, uint32 index) pure returns (ShareClassId scId) {
return ShareClassId.wrap(bytes16((uint128(PoolId.unwrap(poolId)) << 64) + index));
}
using {isNull, raw, equals as ==} for ShareClassId global;// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
import {IERC6909Decimals} from "src/misc/interfaces/IERC6909.sol";
import {PoolId} from "src/common/types/PoolId.sol";
import {AssetId} from "src/common/types/AssetId.sol";
interface IHubRegistry is IERC6909Decimals {
event NewAsset(AssetId indexed assetId, uint8 decimals);
event NewPool(PoolId poolId, address indexed manager, AssetId indexed currency);
event UpdateManager(PoolId indexed poolId, address indexed manager, bool canManage);
event SetMetadata(PoolId indexed poolId, bytes metadata);
event UpdateDependency(bytes32 indexed what, address dependency);
event UpdateCurrency(PoolId indexed poolId, AssetId currency);
error NonExistingPool(PoolId id);
error AssetAlreadyRegistered();
error PoolAlreadyRegistered();
error EmptyAccount();
error EmptyCurrency();
error EmptyShareClassManager();
error AssetNotFound();
/// @notice Register a new asset.
function registerAsset(AssetId assetId, uint8 decimals_) external;
/// @notice Register a new pool.
function registerPool(PoolId poolId, address manager, AssetId currency) external;
/// @notice allow/disallow an address as a manager for the pool
function updateManager(PoolId poolId, address newManager, bool canManage) external;
/// @notice sets metadata for this pool
function setMetadata(PoolId poolId, bytes calldata metadata) external;
/// @notice updates a dependency of the system
function updateDependency(bytes32 what, address dependency) external;
/// @notice updates the currency of the pool
function updateCurrency(PoolId poolId, AssetId currency) external;
/// @notice returns the metadata attached to the pool, if any.
function metadata(PoolId poolId) external view returns (bytes memory);
/// @notice returns the currency of the pool
function currency(PoolId poolId) external view returns (AssetId);
/// @notice returns the dependency used in the system
function dependency(bytes32 what) external view returns (address);
/// @notice returns whether the account is a manager
function manager(PoolId poolId, address who) external view returns (bool);
/// @notice compute a pool ID given an ID postfix
function poolId(uint16 centrifugeId, uint48 postfix) external view returns (PoolId poolId);
/// @notice returns the decimals for an asset
function decimals(AssetId assetId) external view returns (uint8);
/// @notice returns the decimals for a pool
function decimals(PoolId poolId) external view returns (uint8);
/// @notice checks the existence of a pool
function exists(PoolId poolId) external view returns (bool);
/// @notice checks the existence of an asset
function isRegistered(AssetId assetId) external view returns (bool);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
import {D18} from "src/misc/types/D18.sol";
import {PoolId} from "src/common/types/PoolId.sol";
import {AssetId} from "src/common/types/AssetId.sol";
import {ShareClassId} from "src/common/types/ShareClassId.sol";
struct EpochRedeemAmounts {
/// @dev Amount of shares pending to be redeemed at time of epoch
uint128 pendingShareAmount;
/// @dev Total approved amount of redeemed share class tokens
uint128 approvedShareAmount;
/// @dev Total asset amount of revoked share class tokens
uint128 payoutAssetAmount;
/// @dev The amount of pool currency per unit of asset at time of approval
D18 pricePoolPerAsset;
/// @dev The amount of pool currency per unit of share at time of revocation
D18 navPoolPerShare;
/// @dev block timestamp when shares of epoch were revoked
uint64 revokedAt;
}
struct EpochInvestAmounts {
/// @dev Total pending asset amount of deposit asset at time of epoch
uint128 pendingAssetAmount;
/// @dev Total approved asset amount of deposit asset
uint128 approvedAssetAmount;
/// @dev Total approved pool amount of deposit asset
uint128 approvedPoolAmount;
/// @dev The amount of pool currency per unit of asset at time of approval
D18 pricePoolPerAsset;
/// @dev The amount of pool currency per unit of share at time of issuance
D18 navPoolPerShare;
/// @dev block timestamp when shares of epoch were issued
uint64 issuedAt;
}
struct UserOrder {
/// @dev Pending amount in deposit asset denomination
uint128 pending;
/// @dev Index of epoch in which last order was made
uint32 lastUpdate;
}
struct ShareClassMetadata {
/// @dev The name of the share class token
string name;
/// @dev The symbol of the share class token
string symbol;
/// @dev The salt of the share class token
bytes32 salt;
}
struct ShareClassMetrics {
/// @dev Total number of shares
uint128 totalIssuance;
/// @dev The latest net asset value per share class token
D18 navPerShare;
}
struct QueuedOrder {
/// @dev Whether the user requested a cancellation which is now queued
bool isCancelling;
/// @dev The queued increased request amount
uint128 amount;
}
enum RequestType {
/// @dev Whether the request is a deposit one
Deposit,
/// @dev Whether the request is a redeem one
Redeem
}
struct EpochId {
uint32 deposit;
uint32 redeem;
uint32 issue;
uint32 revoke;
}
interface IShareClassManager {
/// Events
event AddShareClass(
PoolId indexed poolId, ShareClassId indexed scId, uint32 indexed index, string name, string symbol, bytes32 salt
);
event UpdateMetadata(PoolId indexed poolId, ShareClassId indexed scId, string name, string symbol);
event ApproveDeposits(
PoolId indexed poolId,
ShareClassId indexed scId,
AssetId indexed depositAssetId,
uint32 epoch,
uint128 approvedPoolAmount,
uint128 approvedAssetAmount,
uint128 pendingAssetAmount
);
event ApproveRedeems(
PoolId indexed poolId,
ShareClassId indexed scId,
AssetId indexed payoutAssetId,
uint32 epoch,
uint128 approvedShareAmount,
uint128 pendingShareAmount
);
event IssueShares(
PoolId indexed poolId,
ShareClassId indexed scId,
AssetId indexed depositAssetId,
uint32 epoch,
D18 navPoolPerShare,
D18 navAssetPerShare,
uint128 issuedShareAmount
);
event RemoteIssueShares(
uint16 centrifugeId, PoolId indexed poolId, ShareClassId indexed scId, uint128 issuedShareAmount
);
event RevokeShares(
PoolId indexed poolId,
ShareClassId indexed scId,
AssetId indexed payoutAssetId,
uint32 epoch,
D18 navPoolPerShare,
D18 navAssetPerShare,
uint128 revokedShareAmount,
uint128 revokedAssetAmount,
uint128 revokedPoolAmount
);
event RemoteRevokeShares(
uint16 centrifugeId, PoolId indexed poolId, ShareClassId indexed scId, uint128 revokedShareAmount
);
event ClaimDeposit(
PoolId indexed poolId,
ShareClassId indexed scId,
uint32 epoch,
bytes32 investor,
AssetId indexed depositAssetId,
uint128 paymentAssetAmount,
uint128 pendingAssetAmount,
uint128 claimedShareAmount,
uint64 issuedAt
);
event ClaimRedeem(
PoolId indexed poolId,
ShareClassId indexed scId,
uint32 epoch,
bytes32 investor,
AssetId indexed payoutAssetId,
uint128 paymentShareAmount,
uint128 pendingShareAmount,
uint128 claimedAssetAmount,
uint64 revokedAt
);
event AddShareClass(PoolId indexed poolId, ShareClassId indexed scId, uint32 indexed index);
event UpdateShareClass(PoolId indexed poolId, ShareClassId indexed scId, D18 navPoolPerShare);
event UpdateDepositRequest(
PoolId indexed poolId,
ShareClassId indexed scId,
AssetId indexed depositAssetId,
uint32 epoch,
bytes32 investor,
uint128 pendingUserAssetAmount,
uint128 pendingTotalAssetAmount,
uint128 queuedUserAssetAmount,
bool pendingCancellation
);
event UpdateRedeemRequest(
PoolId indexed poolId,
ShareClassId indexed scId,
AssetId indexed payoutAssetId,
uint32 epoch,
bytes32 investor,
uint128 pendingUserShareAmount,
uint128 pendingTotalShareAmount,
uint128 queuedUserShareAmount,
bool pendingCancellation
);
/// Errors
error EpochNotInSequence(uint32 providedEpoch, uint32 nowEpoch);
error NoOrderFound();
error InsufficientPending();
error ApprovalRequired();
error IssuanceRequired();
error AlreadyIssued();
error RevocationRequired();
error ZeroApprovalAmount();
error InvalidMetadataSize();
error InvalidMetadataName();
error InvalidMetadataSymbol();
error InvalidSalt();
error AlreadyUsedSalt();
error RevokeMoreThanIssued();
error PoolMissing();
error ShareClassNotFound();
error EpochNotFound();
error DecreaseMoreThanIssued();
error CancellationQueued();
error CancellationInitializationRequired();
/// Functions
/// @notice Creates or updates a request to deposit (exchange) an asset amount for share class tokens.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param amount Asset token amount which is deposited
/// @param investor Centrifuge Vault address of the entity which is depositing
/// @param depositAssetId Identifier of the asset which the investor used for their deposit request
function requestDeposit(PoolId poolId, ShareClassId scId, uint128 amount, bytes32 investor, AssetId depositAssetId)
external;
/// @notice Cancels a pending deposit request.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param investor Centrifuge Vault address of the entity which is cancelling
/// @param depositAssetId Identifier of the asset which the investor used for their deposit request
/// @return cancelledAssetAmount The deposit amount which was previously pending and is now cancelled. This amount
/// was not potentially (partially) swapped to the pool amount in case the deposit asset cannot be exchanged 1:1
/// into the pool token
function cancelDepositRequest(PoolId poolId, ShareClassId scId, bytes32 investor, AssetId depositAssetId)
external
returns (uint128 cancelledAssetAmount);
/// @notice Force cancels a pending deposit request.
/// Only allowed if the user has cancelled a request at least once before. This is to protect against cancelling a
/// request of a smart contract user that does not support the cancellation interface, and would thus be unable to
/// claim back the cancelled assets.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param investor Centrifuge Vault address of the entity which is cancelling
/// @param depositAssetId Identifier of the asset which the investor used for their deposit request
/// @return cancelledAssetAmount The deposit amount which was previously pending and is now cancelled with force
function forceCancelDepositRequest(PoolId poolId, ShareClassId scId, bytes32 investor, AssetId depositAssetId)
external
returns (uint128 cancelledAssetAmount);
/// @notice Creates or updates a request to redeem (exchange) share class tokens for some asset.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param amount Share class token amount which should be redeemed
/// @param investor Centrifuge Vault address of the entity which is redeeming
/// @param payoutAssetId Identifier of the asset which the investor eventually receives back for their redeemed
/// share class tokens
function requestRedeem(PoolId poolId, ShareClassId scId, uint128 amount, bytes32 investor, AssetId payoutAssetId)
external;
/// @notice Cancels a pending redeem request.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param investor Centrifuge Vault address of the entity which is cancelling
/// @param payoutAssetId Identifier of the asset which the investor eventually receives back for their redeemed
/// share class tokens
/// @return cancelledShareAmount The redeem amount which was previously pending and is now cancelled
function cancelRedeemRequest(PoolId poolId, ShareClassId scId, bytes32 investor, AssetId payoutAssetId)
external
returns (uint128 cancelledShareAmount);
/// @notice Force cancels a pending redeem request.
/// Only allowed if the user has cancelled a request at least once before. This is to protect against cancelling a
/// request of a smart contract user that does not support the cancellation interface, and would thus be unable to
/// claim back the cancelled share class tokens.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param investor Centrifuge Vault address of the entity which is cancelling
/// @param payoutAssetId Identifier of the asset which the investor eventually receives back for their redeemed
/// share class tokens
/// @return cancelledShareAmount The redeem amount which was previously pending and is now cancelled with force
function forceCancelRedeemRequest(PoolId poolId, ShareClassId scId, bytes32 investor, AssetId payoutAssetId)
external
returns (uint128 cancelledShareAmount);
/// @notice Approves an asset amount of all deposit requests for the given triplet of pool id, share class id and
/// deposit asset id.
/// @dev nowDepositEpochId MUST be called sequentially.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param depositAssetId Identifier of the asset locked for the deposit request
/// @param nowDepositEpochId The epoch for which shares will be approved.
/// @param approvedAssetAmount Amount of assets that will be approved for deposit
/// @param pricePoolPerAsset Amount of pool unit one gets for a unit of asset
/// @return pendingAssetAmount Amount of assets still pending for deposit
/// @return approvedPoolAmount Amount of pool units approved for deposit
function approveDeposits(
PoolId poolId,
ShareClassId scId,
AssetId depositAssetId,
uint32 nowDepositEpochId,
uint128 approvedAssetAmount,
D18 pricePoolPerAsset
) external returns (uint128 pendingAssetAmount, uint128 approvedPoolAmount);
/// @notice Approves a share class token amount of all redeem requests for the given triplet of pool id, share class
/// id and payout asset id.
/// @dev nowRedeemEpochId MUST be called sequentially.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param payoutAssetId Identifier of the asset for which all requests want to exchange their share class tokens
/// for
/// @param nowRedeemEpochId The epoch for which shares will be approved.
/// @param approvedShareAmount Amount of shares that will be approved for redemption
/// @param pricePoolPerAsset Amount of pool unit one gets for a unit of asset
/// @return pendingShareAmount Sum of redemption request amounts in share class token amount which was not approved
function approveRedeems(
PoolId poolId,
ShareClassId scId,
AssetId payoutAssetId,
uint32 nowRedeemEpochId,
uint128 approvedShareAmount,
D18 pricePoolPerAsset
) external returns (uint128 pendingShareAmount);
/// @notice Emits new shares for the given identifier based on the provided NAV per share.
/// @dev nowIssueEpochId MUST be called sequentially.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param depositAssetId Identifier of the deposit asset for which shares should be issued
/// @param nowIssueEpochId The epoch for which shares will be issued.
/// @param navPoolPerShare The nav per share value of the share class (in the pool currency denomination. Conversion
/// to asset price is done onchain based on the valuation of the asset at approval)
/// @return issuedShareAmount Amount of shares that have been issued
function issueShares(
PoolId poolId,
ShareClassId scId,
AssetId depositAssetId,
uint32 nowIssueEpochId,
D18 navPoolPerShare
) external returns (uint128 issuedShareAmount, uint128 depositAssetAmount, uint128 depositPoolAmount);
/// @notice Take back shares for the given identifier based on the provided NAV per share.
/// @dev nowRevokeEpochId MUST be called sequentially.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param payoutAssetId Identifier of the payout asset
/// @param nowRevokeEpochId The epoch for which shares will be revoked.
/// @param navPoolPerShare The nav per share value of the share class (in the pool currency denomination. Conversion
/// to asset price is done onchain based on the valuation of the asset at approval)
/// @return revokedShareAmount Amount of shares that have been revoked
/// @return payoutAssetAmount Converted amount of payout asset based on number of revoked shares
/// @return payoutPoolAmount Converted amount of pool currency based on number of revoked shares
function revokeShares(
PoolId poolId,
ShareClassId scId,
AssetId payoutAssetId,
uint32 nowRevokeEpochId,
D18 navPoolPerShare
) external returns (uint128 revokedShareAmount, uint128 payoutAssetAmount, uint128 payoutPoolAmount);
/// @notice Collects shares for an investor after their deposit request was (partially) approved and new shares were
/// issued.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param investor Centrifuge Vault address of the recipient of the claimed share class tokens
/// @param depositAssetId Identifier of the asset which the investor used for their deposit request
/// @return payoutShareAmount Amount of shares which the investor receives
/// @return paymentAssetAmount Amount of deposit asset which was taken as payment
/// @return cancelledAssetAmount Amount of deposit asset which was cancelled due to being queued
/// @return canClaimAgain Whether another call to claimRedeem is needed until investor has fully claimed investments
function claimDeposit(PoolId poolId, ShareClassId scId, bytes32 investor, AssetId depositAssetId)
external
returns (
uint128 payoutShareAmount,
uint128 paymentAssetAmount,
uint128 cancelledAssetAmount,
bool canClaimAgain
);
/// @notice Collects an asset amount for an investor after their redeem request was (partially) approved and shares
/// were revoked.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param investor Centrifuge Vault address of the recipient of the claimed asset amount
/// @param payoutAssetId Identifier of the asset which the investor requested to receive back for their redeemed
/// shares
/// @return payoutAssetAmount Amount of payout amount which the investor receives
/// @return paymentShareAmount Amount of shares which the investor redeemed
/// @return cancelledShareAmount Amount of shares which were cancelled due to being queued
/// @return canClaimAgain Whether another call to claimRedeem is needed until investor has fully claimed redemptions
function claimRedeem(PoolId poolId, ShareClassId scId, bytes32 investor, AssetId payoutAssetId)
external
returns (
uint128 payoutAssetAmount,
uint128 paymentShareAmount,
uint128 cancelledShareAmount,
bool canClaimAgain
);
/// @notice Update the share class issuance
///
/// @param centrifugeId Identifier of the chain
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param amount The amount to increase the share class issuance by
/// @param isIssuance Whether it is an issuance or revocation
function updateShares(uint16 centrifugeId, PoolId poolId, ShareClassId scId, uint128 amount, bool isIssuance)
external;
/// @notice Adds a new share class to the given pool.
///
/// @param poolId Identifier of the pool
/// @param name The name of the share class
/// @param symbol The symbol of the share class
/// @param salt The salt used for deploying the share class tokens
/// @return scId Identifier of the newly added share class
function addShareClass(PoolId poolId, string calldata name, string calldata symbol, bytes32 salt)
external
returns (ShareClassId scId);
/// @notice Updates the price pool unit per share unit of a share class
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param pricePoolPerShare The price per share of the share class (in the pool currency denomination)
function updateSharePrice(PoolId poolId, ShareClassId scId, D18 pricePoolPerShare) external;
/// @notice Updates the metadata of a share class.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
/// @param name The name of the share class
/// @param symbol The symbol of the share class
function updateMetadata(PoolId poolId, ShareClassId scId, string calldata name, string calldata symbol) external;
/// @notice Returns the number of share classes for the given pool
///
/// @param poolId Identifier of the pool in question
/// @return count Number of share classes for the given pool
function shareClassCount(PoolId poolId) external view returns (uint32 count);
/// @notice Checks the existence of a share class.
///
/// @param poolId Identifier of the pool
/// @param scId Identifier of the share class
function exists(PoolId poolId, ShareClassId scId) external view returns (bool);
/// @notice Returns the current ongoing epoch id for deposits
///
/// @param scId Identifier of the share class
/// @param depositAssetId AssetId of the payment asset
function nowDepositEpoch(ShareClassId scId, AssetId depositAssetId) external view returns (uint32);
/// @notice Returns the epoch for which will be issued next
///
/// @param scId Identifier of the share class
/// @param depositAssetId AssetId of the payment asset
function nowIssueEpoch(ShareClassId scId, AssetId depositAssetId) external view returns (uint32);
/// @notice Returns the current ongoing epoch id for deposits
///
/// @param scId Identifier of the share class
/// @param payoutAssetId AssetId of the payment asset
function nowRedeemEpoch(ShareClassId scId, AssetId payoutAssetId) external view returns (uint32);
/// @notice Returns the epoch for which will be revoked next
///
/// @param scId Identifier of the share class
/// @param depositAssetId AssetId of the payment asset
function nowRevokeEpoch(ShareClassId scId, AssetId depositAssetId) external view returns (uint32);
/// @notice Returns an upper bound for possible calls to `function claimDeposit(..)`
///
/// @param scId Identifier of the share class
/// @param investor Recipient of the share class tokens
/// @param depositAssetId AssetId of the payment asset
function maxDepositClaims(ShareClassId scId, bytes32 investor, AssetId depositAssetId)
external
view
returns (uint32 maxClaims);
/// @notice Returns an upper bound for possible calls to `function claimRedeem(..)`
///
/// @param scId Identifier of the share class
/// @param investor Recipient of the payout assets
/// @param payoutAssetId AssetId of the payout asset
function maxRedeemClaims(ShareClassId scId, bytes32 investor, AssetId payoutAssetId)
external
view
returns (uint32 maxClaims);
/// @notice Exposes relevant metrics for a share class
///
/// @return totalIssuance The total number of shares known to the Hub side
/// @return pricePoolPerShare The amount of pool units per unit share
function metrics(ShareClassId scId) external view returns (uint128 totalIssuance, D18 pricePoolPerShare);
/// @notice Exposes issuance of a share class on a given network
///
/// @param scId Identifier of the share class
/// @param centrifugeId Identifier of the chain
function issuance(ShareClassId scId, uint16 centrifugeId) external view returns (uint128);
/// @notice Determines the next share class id for the given pool.
///
/// @param poolId Identifier of the pool
/// @return scId Identifier of the next share class
function previewNextShareClassId(PoolId poolId) external view returns (ShareClassId scId);
/// @notice Determines the share class id for the given pool and index.
///
/// @param poolId Identifier of the pool
/// @param index The pool-internal index of the share class id
/// @return scId Identifier of the underlying share class
function previewShareClassId(PoolId poolId, uint32 index) external pure returns (ShareClassId scId);
/// @notice returns The metadata of the share class.
///
/// @param scId Identifier of the share class
/// @return name The registered name of the share class token
/// @return symbol The registered symbol of the share class token
/// @return salt The registered salt of the share class token, used for deterministic deployments
function metadata(ShareClassId scId) external returns (string memory name, string memory symbol, bytes32 salt);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
interface IAuth {
event Rely(address indexed user);
event Deny(address indexed user);
error NotAuthorized();
/// @notice Returns whether the target is a ward (has admin access)
function wards(address target) external view returns (uint256);
/// @notice Make user a ward (give them admin access)
function rely(address user) external;
/// @notice Remove user as a ward (remove admin access)
function deny(address user) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title IERC20
/// @dev Interface of the ERC20 standard as defined in the EIP.
/// @author Modified from OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
interface IERC20 {
error InvalidAddress();
error InsufficientBalance();
error InsufficientAllowance();
/**
* @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 value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` 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 value) external returns (bool);
}
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
error PermitExpired();
error InvalidPermit();
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
interface IERC20Wrapper {
/**
* @dev Returns the address of the underlying ERC-20 token that is being wrapped.
*/
function underlying() external view returns (address);
/**
* @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.
*/
function depositFor(address account, uint256 value) external returns (bool);
/**
* @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.
*/
function withdrawTo(address account, uint256 value) external returns (bool);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
import {IERC165} from "forge-std/interfaces/IERC165.sol";
interface IERC6909 is IERC165 {
error EmptyOwner();
error EmptyAmount();
error InvalidTokenId();
error InsufficientBalance(address owner, uint256 tokenId);
error InsufficientAllowance(address sender, uint256 tokenId);
event OperatorSet(address indexed owner, address indexed operator, bool approved);
event Approval(address indexed owner, address indexed spender, uint256 indexed tokenId, uint256 amount);
event Transfer(address caller, address indexed from, address indexed to, uint256 indexed tokenId, uint256 amount);
/// @notice Owner balance of a tokenId.
/// @param owner The address of the owner.
/// @param tokenId The id of the token.
/// @return amount The balance of the token.
function balanceOf(address owner, uint256 tokenId) external view returns (uint256 amount);
/// @notice Spender allowance of a tokenId.
/// @param owner The address of the owner.
/// @param spender The address of the spender.
/// @param tokenId The id of the token.
/// @return amount The allowance of the token.
function allowance(address owner, address spender, uint256 tokenId) external view returns (uint256 amount);
/// @notice Checks if a spender is approved by an owner as an operator.
/// @param owner The address of the owner.
/// @param spender The address of the spender.
/// @return approved The approval status.
function isOperator(address owner, address spender) external view returns (bool approved);
/// @notice Transfers an amount of a tokenId from the caller to a receiver.
/// @param receiver The address of the receiver.
/// @param tokenId The id of the token.
/// @param amount The amount of the token.
/// @return bool True, always, unless the function reverts.
function transfer(address receiver, uint256 tokenId, uint256 amount) external returns (bool);
/// @notice Transfers an amount of a tokenId from a sender to a receiver.
/// @param sender The address of the sender.
/// @param receiver The address of the receiver.
/// @param tokenId The id of the token.
/// @param amount The amount of the token.
/// @return bool True, always, unless the function reverts.
function transferFrom(address sender, address receiver, uint256 tokenId, uint256 amount) external returns (bool);
/// @notice Approves an amount of a tokenId to a spender.
/// @param spender The address of the spender.
/// @param tokenId The id of the token.
/// @param amount The amount of the token.
/// @return bool True, always.
function approve(address spender, uint256 tokenId, uint256 amount) external returns (bool);
/// @notice Sets or removes an operator for the caller.
/// @param operator The address of the operator.
/// @param approved The approval status.
/// @return bool True, always.
function setOperator(address operator, bool approved) external returns (bool);
}
interface IERC6909URIExt {
event TokenURISet(uint256 indexed tokenId, string uri);
event ContractURISet(address indexed target, string uri);
error EmptyURI();
/// @return uri Returns the common token URI.
function contractURI() external view returns (string memory);
/// @dev Returns empty string if tokenId does not exist.
/// MAY implemented to throw MissingURI(tokenId) error.
/// @param tokenId The token to query URI for.
/// @return uri A string representing the uri for the specific tokenId.
function tokenURI(uint256 tokenId) external view returns (string memory);
}
interface IERC6909NFT is IERC6909, IERC6909URIExt {
error UnknownTokenId(address owner, uint256 tokenId);
error LessThanMinimalDecimal(uint8 minimal, uint8 actual);
/// @notice Provide URI for a specific tokenId.
/// @param tokenId Token Id.
/// @param URI URI to a document defining the collection as a whole.
function setTokenURI(uint256 tokenId, string memory URI) external;
/// @dev Optional method to set up the contract URI if needed.
/// @param URI URI to a document defining the collection as a whole.
function setContractURI(string memory URI) external;
/// @notice Mint new tokens for a given owner and sets tokenURI.
/// @dev For non-fungible tokens, call with amount = 1, for fungible it could be any amount.
/// TokenId is auto incremented by one.
///
/// @param owner Creates supply of a given tokenId by amount for owner.
/// @param tokenURI URI fortestBurningToken the newly minted token.
/// @return tokenId Id of the newly minted token.
function mint(address owner, string memory tokenURI) external returns (uint256 tokenId);
/// @notice Destroy supply of a given tokenId by amount.
/// @dev The msg.sender MUST be the owner.
///
/// @param tokenId Item which have reduced supply.
function burn(uint256 tokenId) external;
}
/// @notice Extension of ERC6909 Standard for tracking total supply
interface IERC6909TotalSupplyExt {
/// @notice The totalSupply for a token id.
///
/// @param tokenId Id of the token
/// @return supply Total supply for a given `tokenId`
function totalSupply(uint256 tokenId) external returns (uint256 supply);
}
interface IERC6909Decimals {
/// @notice Used to retrieve the decimals of an asset
/// @dev address is used but the value corresponds to a AssetId
function decimals(uint256 assetId) external view returns (uint8);
}
interface IERC6909MetadataExt is IERC6909Decimals {
/// @notice Used to retrieve the decimals of an asset
/// @dev address is used but the value corresponds to a AssetId
function decimals(uint256 assetId) external view returns (uint8);
/// @notice Used to retrieve the name of an asset
/// @dev address is used but the value corresponds to a AssetId
function name(uint256 assetId) external view returns (string memory);
/// @notice Used to retrieve the symbol of an asset
/// @dev address is used but the value corresponds to a AssetId
function symbol(uint256 assetId) external view returns (string memory);
}
interface IERC6909Fungible is IERC6909 {
/// @notice Mint new tokens for a specific tokenid and assign them to an owner
///
/// @param owner Creates supply of a given `tokenId` by `amount` for owner.
/// @param tokenId Id of the item
/// @param amount Adds `amount` to the total supply of the given `tokenId`
function mint(address owner, uint256 tokenId, uint256 amount) external;
/// @notice Destroy supply of a given tokenId by amount.
/// @dev The msg.sender MUST be the owner.
///
/// @param owner Owner of the `tokenId`
/// @param tokenId Id of the item.
/// @param amount Subtract `amount` from the total supply of the given `tokenId`
function burn(address owner, uint256 tokenId, uint256 amount) external;
/// @notice Enforces a transfer from `spender` point of view.
///
///
/// @param sender The owner of the `tokenId`
/// @param receiver Address of the receiving party
/// @param tokenId Token Id
/// @param amount Amount to be transferred
function authTransferFrom(address sender, address receiver, uint256 tokenId, uint256 amount)
external
returns (bool);
}
/// @dev A factory contract to deploy new collateral contracts implementing IERC6909.
interface IERC6909Factory {
/// Events
event NewTokenDeployment(address indexed owner, address instance);
/// @notice Deploys new install of a contract that implements IERC6909.
/// @dev Factory should deploy deterministically if possible.
///
/// @param owner Owner of the deployed collateral contract which has initial full rights.
/// @param salt Used to make a deterministic deployment.
/// @return An address of the newly deployed contract.
function deploy(address owner, bytes32 salt) external returns (address);
/// @notice Generates a new deterministic address based on the owner and the salt.
///
/// @param owner Owner of the deployed collateral contract which has initial full rights.
/// @param salt Used to make a deterministic deployment.
/// @return An address of the newly deployed contract.
function previewAddress(address owner, bytes32 salt) external returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;
interface IERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}{
"remappings": [
"forge-std/=lib/forge-std/src/",
"@chimera/=lib/chimera/src/",
"createx-forge/=lib/createx-forge/",
"chimera/=lib/chimera/src/",
"ds-test/=lib/chimera/lib/forge-std/lib/ds-test/src/",
"setup-helpers/=lib/setup-helpers/src/"
],
"optimizer": {
"enabled": true,
"runs": 1
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IHubRegistry","name":"hubRegistry_","type":"address"},{"internalType":"address","name":"deployer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyIssued","type":"error"},{"inputs":[],"name":"AlreadyUsedSalt","type":"error"},{"inputs":[],"name":"ApprovalRequired","type":"error"},{"inputs":[],"name":"CancellationInitializationRequired","type":"error"},{"inputs":[],"name":"CancellationQueued","type":"error"},{"inputs":[],"name":"DecreaseMoreThanIssued","type":"error"},{"inputs":[],"name":"EpochNotFound","type":"error"},{"inputs":[{"internalType":"uint32","name":"providedEpoch","type":"uint32"},{"internalType":"uint32","name":"nowEpoch","type":"uint32"}],"name":"EpochNotInSequence","type":"error"},{"inputs":[],"name":"InsufficientPending","type":"error"},{"inputs":[],"name":"InvalidMetadataName","type":"error"},{"inputs":[],"name":"InvalidMetadataSize","type":"error"},{"inputs":[],"name":"InvalidMetadataSymbol","type":"error"},{"inputs":[],"name":"InvalidSalt","type":"error"},{"inputs":[],"name":"IssuanceRequired","type":"error"},{"inputs":[],"name":"MulDiv_Overflow","type":"error"},{"inputs":[],"name":"NoOrderFound","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"PoolMissing","type":"error"},{"inputs":[],"name":"RevocationRequired","type":"error"},{"inputs":[],"name":"RevokeMoreThanIssued","type":"error"},{"inputs":[],"name":"ShareClassNotFound","type":"error"},{"inputs":[],"name":"Uint128_Overflow","type":"error"},{"inputs":[],"name":"Uint64_Overflow","type":"error"},{"inputs":[],"name":"ZeroApprovalAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"uint32","name":"index","type":"uint32"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"AddShareClass","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"uint32","name":"index","type":"uint32"}],"name":"AddShareClass","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"AssetId","name":"depositAssetId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"},{"indexed":false,"internalType":"uint128","name":"approvedPoolAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"approvedAssetAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"pendingAssetAmount","type":"uint128"}],"name":"ApproveDeposits","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"AssetId","name":"payoutAssetId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"},{"indexed":false,"internalType":"uint128","name":"approvedShareAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"pendingShareAmount","type":"uint128"}],"name":"ApproveRedeems","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"investor","type":"bytes32"},{"indexed":true,"internalType":"AssetId","name":"depositAssetId","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"paymentAssetAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"pendingAssetAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"claimedShareAmount","type":"uint128"},{"indexed":false,"internalType":"uint64","name":"issuedAt","type":"uint64"}],"name":"ClaimDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"investor","type":"bytes32"},{"indexed":true,"internalType":"AssetId","name":"payoutAssetId","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"paymentShareAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"pendingShareAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"claimedAssetAmount","type":"uint128"},{"indexed":false,"internalType":"uint64","name":"revokedAt","type":"uint64"}],"name":"ClaimRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Deny","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"AssetId","name":"depositAssetId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"},{"indexed":false,"internalType":"D18","name":"navPoolPerShare","type":"uint128"},{"indexed":false,"internalType":"D18","name":"navAssetPerShare","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"issuedShareAmount","type":"uint128"}],"name":"IssueShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Rely","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":false,"internalType":"uint128","name":"issuedShareAmount","type":"uint128"}],"name":"RemoteIssueShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":false,"internalType":"uint128","name":"revokedShareAmount","type":"uint128"}],"name":"RemoteRevokeShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"AssetId","name":"payoutAssetId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"},{"indexed":false,"internalType":"D18","name":"navPoolPerShare","type":"uint128"},{"indexed":false,"internalType":"D18","name":"navAssetPerShare","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"revokedShareAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"revokedAssetAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"revokedPoolAmount","type":"uint128"}],"name":"RevokeShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"AssetId","name":"depositAssetId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"investor","type":"bytes32"},{"indexed":false,"internalType":"uint128","name":"pendingUserAssetAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"pendingTotalAssetAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"queuedUserAssetAmount","type":"uint128"},{"indexed":false,"internalType":"bool","name":"pendingCancellation","type":"bool"}],"name":"UpdateDepositRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"}],"name":"UpdateMetadata","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"AssetId","name":"payoutAssetId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"investor","type":"bytes32"},{"indexed":false,"internalType":"uint128","name":"pendingUserShareAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"pendingTotalShareAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"queuedUserShareAmount","type":"uint128"},{"indexed":false,"internalType":"bool","name":"pendingCancellation","type":"bool"}],"name":"UpdateRedeemRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":false,"internalType":"D18","name":"navPoolPerShare","type":"uint128"}],"name":"UpdateShareClass","type":"event"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"addShareClass","outputs":[{"internalType":"ShareClassId","name":"scId_","type":"bytes16"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"},{"internalType":"bytes32","name":"investor","type":"bytes32"}],"name":"allowForceDepositCancel","outputs":[{"internalType":"bool","name":"cancelled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"},{"internalType":"bytes32","name":"investor","type":"bytes32"}],"name":"allowForceRedeemCancel","outputs":[{"internalType":"bool","name":"cancelled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"},{"internalType":"uint32","name":"nowDepositEpochId","type":"uint32"},{"internalType":"uint128","name":"approvedAssetAmount","type":"uint128"},{"internalType":"D18","name":"pricePoolPerAsset","type":"uint128"}],"name":"approveDeposits","outputs":[{"internalType":"uint128","name":"pendingAssetAmount","type":"uint128"},{"internalType":"uint128","name":"approvedPoolAmount","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"},{"internalType":"uint32","name":"nowRedeemEpochId","type":"uint32"},{"internalType":"uint128","name":"approvedShareAmount","type":"uint128"},{"internalType":"D18","name":"pricePoolPerAsset","type":"uint128"}],"name":"approveRedeems","outputs":[{"internalType":"uint128","name":"pendingShareAmount","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"bytes32","name":"investor","type":"bytes32"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"}],"name":"cancelDepositRequest","outputs":[{"internalType":"uint128","name":"cancelledAssetAmount","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"bytes32","name":"investor","type":"bytes32"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"}],"name":"cancelRedeemRequest","outputs":[{"internalType":"uint128","name":"cancelledShareAmount","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"bytes32","name":"investor","type":"bytes32"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"}],"name":"claimDeposit","outputs":[{"internalType":"uint128","name":"payoutShareAmount","type":"uint128"},{"internalType":"uint128","name":"paymentAssetAmount","type":"uint128"},{"internalType":"uint128","name":"cancelledAssetAmount","type":"uint128"},{"internalType":"bool","name":"canClaimAgain","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"bytes32","name":"investor","type":"bytes32"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"}],"name":"claimRedeem","outputs":[{"internalType":"uint128","name":"payoutAssetAmount","type":"uint128"},{"internalType":"uint128","name":"paymentShareAmount","type":"uint128"},{"internalType":"uint128","name":"cancelledShareAmount","type":"uint128"},{"internalType":"bool","name":"canClaimAgain","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"deny","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"},{"internalType":"bytes32","name":"investor","type":"bytes32"}],"name":"depositRequest","outputs":[{"internalType":"uint128","name":"pending","type":"uint128"},{"internalType":"uint32","name":"lastUpdate","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"}],"name":"epochId","outputs":[{"internalType":"uint32","name":"deposit","type":"uint32"},{"internalType":"uint32","name":"redeem","type":"uint32"},{"internalType":"uint32","name":"issue","type":"uint32"},{"internalType":"uint32","name":"revoke","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"},{"internalType":"uint32","name":"epochId_","type":"uint32"}],"name":"epochInvestAmounts","outputs":[{"internalType":"uint128","name":"pendingAssetAmount","type":"uint128"},{"internalType":"uint128","name":"approvedAssetAmount","type":"uint128"},{"internalType":"uint128","name":"approvedPoolAmount","type":"uint128"},{"internalType":"D18","name":"pricePoolPerAsset","type":"uint128"},{"internalType":"D18","name":"navPoolPerShare","type":"uint128"},{"internalType":"uint64","name":"issuedAt","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"},{"internalType":"uint32","name":"epochId_","type":"uint32"}],"name":"epochRedeemAmounts","outputs":[{"internalType":"uint128","name":"pendingShareAmount","type":"uint128"},{"internalType":"uint128","name":"approvedShareAmount","type":"uint128"},{"internalType":"uint128","name":"payoutAssetAmount","type":"uint128"},{"internalType":"D18","name":"pricePoolPerAsset","type":"uint128"},{"internalType":"D18","name":"navPoolPerShare","type":"uint128"},{"internalType":"uint64","name":"revokedAt","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"bytes32","name":"investor","type":"bytes32"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"}],"name":"forceCancelDepositRequest","outputs":[{"internalType":"uint128","name":"cancelledAssetAmount","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"bytes32","name":"investor","type":"bytes32"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"}],"name":"forceCancelRedeemRequest","outputs":[{"internalType":"uint128","name":"cancelledShareAmount","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hubRegistry","outputs":[{"internalType":"contract IHubRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"uint16","name":"centrifugeId","type":"uint16"}],"name":"issuance","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"},{"internalType":"uint32","name":"nowIssueEpochId","type":"uint32"},{"internalType":"D18","name":"navPoolPerShare","type":"uint128"}],"name":"issueShares","outputs":[{"internalType":"uint128","name":"issuedShareAmount","type":"uint128"},{"internalType":"uint128","name":"depositAssetAmount","type":"uint128"},{"internalType":"uint128","name":"depositPoolAmount","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"bytes32","name":"investor","type":"bytes32"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"}],"name":"maxDepositClaims","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"bytes32","name":"investor","type":"bytes32"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"}],"name":"maxRedeemClaims","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"}],"name":"metadata","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"}],"name":"metrics","outputs":[{"internalType":"uint128","name":"totalIssuance","type":"uint128"},{"internalType":"D18","name":"navPerShare","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"}],"name":"nowDepositEpoch","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"}],"name":"nowIssueEpoch","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"}],"name":"nowRedeemEpoch","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"}],"name":"nowRevokeEpoch","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"}],"name":"pendingDeposit","outputs":[{"internalType":"uint128","name":"pending","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"}],"name":"pendingRedeem","outputs":[{"internalType":"uint128","name":"pending","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"}],"name":"previewNextShareClassId","outputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"uint32","name":"index","type":"uint32"}],"name":"previewShareClassId","outputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"},{"internalType":"bytes32","name":"investor","type":"bytes32"}],"name":"queuedDepositRequest","outputs":[{"internalType":"bool","name":"isCancelling","type":"bool"},{"internalType":"uint128","name":"amount","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"},{"internalType":"bytes32","name":"investor","type":"bytes32"}],"name":"queuedRedeemRequest","outputs":[{"internalType":"bool","name":"isCancelling","type":"bool"},{"internalType":"uint128","name":"amount","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"},{"internalType":"bytes32","name":"investor","type":"bytes32"}],"name":"redeemRequest","outputs":[{"internalType":"uint128","name":"pending","type":"uint128"},{"internalType":"uint32","name":"lastUpdate","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rely","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"bytes32","name":"investor","type":"bytes32"},{"internalType":"AssetId","name":"depositAssetId","type":"uint128"}],"name":"requestDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"bytes32","name":"investor","type":"bytes32"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"}],"name":"requestRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"AssetId","name":"payoutAssetId","type":"uint128"},{"internalType":"uint32","name":"nowRevokeEpochId","type":"uint32"},{"internalType":"D18","name":"navPoolPerShare","type":"uint128"}],"name":"revokeShares","outputs":[{"internalType":"uint128","name":"revokedShareAmount","type":"uint128"},{"internalType":"uint128","name":"payoutAssetAmount","type":"uint128"},{"internalType":"uint128","name":"payoutPoolAmount","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"salts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"}],"name":"shareClassCount","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"","type":"bytes16"}],"name":"shareClassIds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"name":"updateMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"D18","name":"navPoolPerShare","type":"uint128"}],"name":"updateSharePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId_","type":"bytes16"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"bool","name":"isIssuance","type":"bool"}],"name":"updateShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a060405234801561000f575f5ffd5b50604051614a8f380380614a8f83398101604081905261002e9161009b565b6001600160a01b0381165f8181526020819052604080822060019055518392917fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a6091a250506001600160a01b03166080526100d3565b6001600160a01b0381168114610098575f5ffd5b50565b5f5f604083850312156100ac575f5ffd5b82516100b781610084565b60208401519092506100c881610084565b809150509250929050565b60805161496561012a5f395f81816108ed01528181610b9e01528181610c41015281816111080152818161119b01528181611a6b015281816123bb0152818161244601528181612c180152612cae01526149655ff3fe608060405234801561000f575f5ffd5b5060043610610218575f3560e01c80630162c7511461021c578063029dbcfe1461024957806305a3aff91461028957806314e2acc9146102f55780631577b7a1146103285780631633f3c11461035457806317ef047a146103675780631ac1e1d51461037a578063293d4b84146103b75780632c1917ee1461046e5780633ba3d070146104d05780633cc7116b146104f557806346bfcc8f1461050a5780634d61dc291461051d5780634e1ea2cd14610560578063516a6a74146105df57806365fae35e146106125780636787053c146106255780637315cf5814610638578063790b56ce1461066b5780637dea42b31461067e57806386a672dd146106c65780638a6fd02a146107325780638baa4083146107655780638bd95b44146107785780638c34e9331461078b5780639b884cd5146107ce5780639c52a7f1146107e15780639ea3d094146107f4578063a3bfe16814610816578063a822014914610829578063aa903d731461083c578063bec24d911461084f578063bf353dbb14610862578063c4035bd01461088f578063c4d49aa3146108a2578063c7ade5c0146108b5578063c88854a3146108e8578063d0d4133114610927578063db254ea71461093a578063ddcdfa3414610982578063e6d283a614610995578063ec762bfe146109b7578063efdd0d0e146109ca578063fb868432146109dd578063fbd2ab3e14610a0a575b5f5ffd5b61022f61022a366004613df7565b610a1d565b60405163ffffffff90911681526020015b60405180910390f35b61027c610257366004613df7565b600a60209081525f92835260408084209091529082529020546001600160801b031681565b6040516102409190613e2c565b6102d1610297366004613e40565b600c60209081525f93845260408085208252928452828420905282529020546001600160801b03811690600160801b900463ffffffff1682565b604080516001600160801b03909316835263ffffffff909116602083015201610240565b610308610303366004613ea5565b610a6b565b604080516001600160801b03938416815292909116602083015201610240565b61033b610336366004613f1d565b610e0d565b6040516001600160801b03199091168152602001610240565b61027c610362366004613f36565b610e41565b61033b610375366004613f82565b610f41565b61038d610388366004613fb3565b610f4c565b604080516001600160801b0394851681529284166020840152921691810191909152606001610240565b6104236103c536600461401a565b600960209081525f93845260408085208252928452828420905282529020805460018201546002909201546001600160801b0380831693600160801b938490048216938282169391819004831692821691046001600160401b031686565b604080516001600160801b039788168152958716602087015293861693850193909352908416606084015290921660808201526001600160401b0390911660a082015260c001610240565b6104b161047c366004613e40565b600f60209081525f938452604080852082529284528284209052825290205460ff81169061010090046001600160801b031682565b6040805192151583526001600160801b03909116602083015201610240565b61022f6104de366004613f1d565b60026020525f908152604090205463ffffffff1681565b61050861050336600461406d565b6113b3565b005b61027c610518366004613f36565b611668565b61055061052b366004613e40565b601060209081525f938452604080852082529284528284209052825290205460ff1681565b6040519015158152602001610240565b6105af61056e366004613df7565b600760209081525f928352604080842090915290825290205463ffffffff80821691600160201b8104821691600160401b8204811691600160601b90041684565b6040805163ffffffff95861681529385166020850152918416918301919091529091166060820152608001610240565b61027c6105ed3660046140ca565b600660209081525f92835260408084209091529082529020546001600160801b031681565b6105086106203660046140f2565b611731565b61022f610633366004613df7565b6117a4565b610308610646366004614118565b60036020525f90815260409020546001600160801b0380821691600160801b90041682565b610508610679366004614131565b6117e9565b61069161068c366004613f36565b611857565b60405161024094939291906001600160801b039485168152928416602084015292166040820152901515606082015260800190565b6104236106d436600461401a565b600860209081525f93845260408085208252928452828420905282529020805460018201546002909201546001600160801b0380831693600160801b938490048216938282169391819004831692821691046001600160401b031686565b610550610740366004613e40565b601160209081525f938452604080852082529284528284209052825290205460ff1681565b610508610773366004614131565b611c5f565b6105086107863660046141c7565b611cc6565b6104b1610799366004613e40565b600e60209081525f938452604080852082529284528284209052825290205460ff81169061010090046001600160801b031682565b61027c6107dc366004613f36565b611d84565b6105086107ef3660046140f2565b611e50565b610807610802366004614118565b611ec2565b60405161024093929190614283565b61027c610824366004613f36565b611fef565b61022f6108373660046142b8565b6120e6565b61022f61084a366004613df7565b61216e565b61069161085d366004613f36565b6121b3565b6108816108703660046140f2565b5f6020819052908152604090205481565b604051908152602001610240565b61022f61089d3660046142b8565b61268c565b61022f6108b0366004613df7565b612703565b61027c6108c3366004613df7565b600b60209081525f92835260408084209091529082529020546001600160801b031681565b61090f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610240565b61027c610935366004613ea5565b612741565b6102d1610948366004613e40565b600d60209081525f93845260408085208252928452828420905282529020546001600160801b03811690600160801b900463ffffffff1682565b6105086109903660046142f5565b6129c5565b6105506109a336600461432e565b60016020525f908152604090205460ff1681565b61038d6109c5366004613fb3565b612a98565b61033b6109d8366004614345565b612e4f565b6105506109eb3660046143cb565b600560209081525f928352604080842090915290825290205460ff1681565b610550610a183660046143cb565b612f6f565b6001600160801b031982165f9081526007602090815260408083206001600160801b0385168452909152812054610a6290600160401b900463ffffffff166001614407565b90505b92915050565b335f908152602081905260408120548190600114610a9c5760405163ea8e4eb560e01b815260040160405180910390fd5b610aa68888612f6f565b610ac357604051631eda274960e21b815260040160405180910390fd5b610acd8787612703565b63ffffffff168563ffffffff161485610ae68989612703565b9091610b1057604051632c647e3760e21b8152600401610b07929190614423565b60405180910390fd5b50506001600160801b031987165f908152600b602090815260408083206001600160801b038a81168552925290912054811692508416821015610b665760405163776a3aa960e11b815260040160405180910390fd5b5f846001600160801b031611610b8f5760405163035a9e4760e11b815260040160405180910390fd5b610cbb846001600160801b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166309d2f9b4896040518263ffffffff1660e01b8152600401610be89190613e2c565b602060405180830381865afa158015610c03573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c27919061443a565b604051600162fe590960e01b031981526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ff01a6f790610c76908e9060040161445a565b602060405180830381865afa158015610c91573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cb5919061443a565b86612fa5565b6001600160801b03198089165f8181526008602090815260408083206001600160801b038d811680865291845282852063ffffffff8e16865284528285208a82168d8316600160801b9081029099161781558b8216909702818916176001880155948452600b8352818420908452909152812080549495509293889392610d449185911661446e565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508483610d74919061446e565b6001600160801b031989165f8181526007602090815260408083206001600160801b038d16808552925291829020805463ffffffff191663ffffffff8c161790559051929550916001600160401b038c16907f1785217365be01fea67dbce22680b382886fe6a3a22156830b3cda5823a42a8e90610df9908b9088908c908b9061448d565b60405180910390a450965096945050505050565b6001600160401b0381165f90815260026020526040812054610a65908390610e3c9063ffffffff166001614407565b612fbc565b335f90815260208190526040812054600114610e705760405163ea8e4eb560e01b815260040160405180910390fd5b610e7a8585612f6f565b610e9757604051631eda274960e21b815260040160405180910390fd5b6001600160801b031984165f9081526010602090815260408083206001600160801b0386168452825280832086845290915290205460ff16610eec57604051635fb581dd60e01b815260040160405180910390fd5b6001600160801b031984165f908152600d602090815260408083206001600160801b0386811685529083528184208785529092528220541690610f3790879087908490888882612fe7565b9695505050505050565b5f610a628383612fbc565b335f9081526020819052604081205481908190600114610f7f5760405163ea8e4eb560e01b815260040160405180910390fd5b610f898888612f6f565b610fa657604051631eda274960e21b815260040160405180910390fd5b6001600160801b031987165f9081526007602090815260408083206001600160801b038a16845290915290205463ffffffff600160201b90910481169086161115611004576040516386d1007760e01b815260040160405180910390fd5b61100e878761216e565b63ffffffff168563ffffffff161485611027898961216e565b909161104857604051632c647e3760e21b8152600401610b07929190614423565b50506001600160801b03198088165f9081526009602090815260408083206001600160801b038b8116855290835281842063ffffffff808c16865293529083206002810180548a8416961686179055805490946110b4949093600160801b909204909216919061327216565b60018201549092506110d590600160801b90046001600160801b031661329c565b6110df575f611234565b8054604051600162fe590960e01b0319815261123491600160801b90046001600160801b0316907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ff01a6f790611145908e9060040161445a565b602060405180830381865afa158015611160573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611184919061443a565b604051630274be6d60e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906309d2f9b4906111d0908d90600401613e2c565b602060405180830381865afa1580156111eb573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061120f919061443a565b600285015460018601546001600160801b0391821691600160801b909104165f6132aa565b81546001830180546001600160801b0319166001600160801b0384811691909117909155600160801b909104169450925061126e426132b9565b600282018054600160801b600160c01b031916600160801b6001600160401b039384168102919091179091556001600160801b03198a165f8181526007602090815260408083206001600160801b038e8116808652919093529220805463ffffffff60601b1916600160601b63ffffffff8e1602179055600186015491949293928e16927f14f07afe7ac79d02cc585b7f76d4d9687e82b16083b19e225a2fde74b32bf36e928c928c9261132392041661329c565b61132d575f611354565b60028701546001880154611354916001600160801b0390811691600160801b9004166132e6565b87546040805163ffffffff90951685526001600160801b03938416602086015291831691840191909152600160801b9004811660608301528881166080830152871660a082015260c0015b60405180910390a450955095509592505050565b335f908152602081905260409020546001146113e25760405163ea8e4eb560e01b815260040160405180910390fd5b6113ec8484612f6f565b61140957604051631eda274960e21b815260040160405180910390fd5b808061144857506001600160801b031983165f90815260066020908152604080832061ffff891684529091529020546001600160801b03808416911610155b61146557604051635fe755ed60e01b815260040160405180910390fd5b5f8161149d576001600160801b031984165f908152600360205260409020546114989084906001600160801b031661446e565b6114ca565b6001600160801b031984165f908152600360205260409020546114ca9084906001600160801b03166144bc565b6001600160801b03198581165f90815260036020526040812080549092166001600160801b038416179091559091508261153f576001600160801b031985165f90815260066020908152604080832061ffff8b16845290915290205461153a9085906001600160801b031661446e565b61157b565b6001600160801b031985165f90815260066020908152604080832061ffff8b16845290915290205461157b9085906001600160801b03166144bc565b6001600160801b03198681165f90815260066020908152604080832061ffff8d168452909152902080549091166001600160801b0383161790559050821561161057846001600160801b031916866001600160401b03167f2c63f350e031a7945cf5c5d46ff2bfb9dbf69c9b401dff10c60d6bb1c4d0687489876040516116039291906144db565b60405180910390a361165f565b846001600160801b031916866001600160401b03167fc2f94e30444446144c04ae7a5e046b226a3640ea83c2c7cf1a0a4fee4be36ff089876040516116569291906144db565b60405180910390a35b50505050505050565b335f908152602081905260408120546001146116975760405163ea8e4eb560e01b815260040160405180910390fd5b6116a18585612f6f565b6116be57604051631eda274960e21b815260040160405180910390fd5b6001600160801b031984165f8181526010602090815260408083206001600160801b038781168086529184528285208986528452828520805460ff19166001179055948452600d8352818420908452825280832087845290915281205490911690610f3790879087908490888882612fe7565b335f908152602081905260409020546001146117605760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b6001600160801b031982165f9081526007602090815260408083206001600160801b0385168452909152812054610a6290600160201b900463ffffffff166001614407565b335f908152602081905260409020546001146118185760405163ea8e4eb560e01b815260040160405180910390fd5b6118228585612f6f565b61183f57604051631eda274960e21b815260040160405180910390fd5b61184f858585600186865f612fe7565b505050505050565b335f9081526020819052604081205481908190819060011461188c5760405163ea8e4eb560e01b815260040160405180910390fd5b6118968888612f6f565b6118b357604051631eda274960e21b815260040160405180910390fd5b6001600160801b031987165f908152600c602090815260408083206001600160801b0389811685529083528184208a8552909252909120805490911661190c5760405163484a885b60e01b815260040160405180910390fd5b6001600160801b031988165f9081526007602090815260408083206001600160801b038a1684529091529020548154600160601b90910463ffffffff908116600160801b90920416111561197357604051639aac3e0b60e01b815260040160405180910390fd5b6001600160801b031988165f8181526007602090815260408083206001600160801b038b81168086529184528285205487549686526009855283862092865291845282852063ffffffff600160801b97889004811680885291909552929094208054600160601b9092049093169091109550909290041615611a215780548254611a1c91611a17916001600160801b0390811691600160801b8104821691166132f1565b6133af565b611a23565b5f5b94506001600160801b03851615611af9576001810154611a5290600160801b90046001600160801b031661329c565b611a5c575f611ab5565b611ab5856001600160801b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ff01a6f78d6040518263ffffffff1660e01b8152600401611145919061445a565b8254909650859083905f90611ad49084906001600160801b031661446e565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b866001600160801b0316896001600160801b0319168b6001600160401b03167fbaedde181510aaa5fcaded7a64ddd81c51a9b07b5ed0209b6e3a92801c93959e855f0160109054906101000a900463ffffffff168c8a885f015f9054906101000a90046001600160801b03168d8960020160109054906101000a90046001600160401b0316604051611b90969594939291906144f8565b60405180910390a481546001600160801b03165f03611bdb57611bb389886117a4565b825463ffffffff91909116600160801b0263ffffffff60801b199091161782555f9250611c1c565b81546001908390601090611bfd908490600160801b900463ffffffff16614407565b92506101000a81548163ffffffff021916908363ffffffff1602179055505b611c2689886117a4565b825463ffffffff918216600160801b90910490911603611c5257611c4f8a8a8a8a8660016133d8565b93505b5050945094509450949050565b335f90815260208190526040902054600114611c8e5760405163ea8e4eb560e01b815260040160405180910390fd5b611c988585612f6f565b611cb557604051631eda274960e21b815260040160405180910390fd5b61184f858585600186866001612fe7565b335f90815260208190526040902054600114611cf55760405163ea8e4eb560e01b815260040160405180910390fd5b611cff8686612f6f565b611d1c57604051631eda274960e21b815260040160405180910390fd5b611d2a85858585855f6135b2565b846001600160801b031916866001600160401b03167f8c0eec6877ffbfd88a45283fadb04a776dc75b31282041dcbc782bb24d3c4a7186868686604051611d749493929190614565565b60405180910390a3505050505050565b335f90815260208190526040812054600114611db35760405163ea8e4eb560e01b815260040160405180910390fd5b611dbd8585612f6f565b611dda57604051631eda274960e21b815260040160405180910390fd5b6001600160801b031984165f8181526011602090815260408083206001600160801b038781168086529184528285208986528452828520805460ff19166001908117909155958552600c84528285209185529083528184208885529092528220541691610f379188918891859189908990612fe7565b335f90815260208190526040902054600114611e7f5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b60046020525f9081526040902080548190611edc9061458b565b80601f0160208091040260200160405190810160405280929190818152602001828054611f089061458b565b8015611f535780601f10611f2a57610100808354040283529160200191611f53565b820191905f5260205f20905b815481529060010190602001808311611f3657829003601f168201915b505050505090806001018054611f689061458b565b80601f0160208091040260200160405190810160405280929190818152602001828054611f949061458b565b8015611fdf5780601f10611fb657610100808354040283529160200191611fdf565b820191905f5260205f20905b815481529060010190602001808311611fc257829003601f168201915b5050505050908060020154905083565b335f9081526020819052604081205460011461201e5760405163ea8e4eb560e01b815260040160405180910390fd5b6120288585612f6f565b61204557604051631eda274960e21b815260040160405180910390fd5b6001600160801b031984165f9081526011602090815260408083206001600160801b0386168452825280832086845290915290205460ff1661209a57604051635fb581dd60e01b815260040160405180910390fd5b6001600160801b031984165f908152600c602090815260408083206001600160801b0386811685529083528184208785529092528220541690610f379087908790849088886001612fe7565b6001600160801b031983165f818152600c602090815260408083206001600160801b0386811680865291845282852088865284528285208351808501855290549182168152600160801b90910463ffffffff90811682860152958552600784528285209185529252822054919261216492600160201b9004166136fb565b90505b9392505050565b6001600160801b031982165f9081526007602090815260408083206001600160801b0385168452909152812054610a6290600160601b900463ffffffff166001614407565b335f908152602081905260408120548190819081906001146121e85760405163ea8e4eb560e01b815260040160405180910390fd5b6121f28888612f6f565b61220f57604051631eda274960e21b815260040160405180910390fd5b6001600160801b031987165f908152600d602090815260408083206001600160801b0389811685529083528184208a855290925290912080549091166122685760405163484a885b60e01b815260040160405180910390fd5b6001600160801b031988165f9081526007602090815260408083206001600160801b038a1684529091529020548154600160401b90910463ffffffff908116600160801b9092041611156122cf57604051638691a7e760e01b815260040160405180910390fd5b6001600160801b031988165f8181526007602090815260408083206001600160801b038b81168086529184528285205487549686526008855283862092865291845282852063ffffffff600160801b97889004811680885291909552929094208054600160401b9092049093169091109550909290041615612378578054825461237391611a17916001600160801b0390811691600160801b8104821691166132f1565b61237a565b5f5b94506001600160801b038516156125375760028101546123a2906001600160801b031661329c565b6123ac575f6124f3565b6124f3856001600160801b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166309d2f9b48a6040518263ffffffff1660e01b81526004016124059190613e2c565b602060405180830381865afa158015612420573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612444919061443a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ff01a6f78e6040518263ffffffff1660e01b8152600401612490919061445a565b602060405180830381865afa1580156124ab573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124cf919061443a565b600185015460028601546001600160801b03600160801b909204821691165f6132aa565b8254909650859083905f906125129084906001600160801b031661446e565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b866001600160801b0316896001600160801b0319168b6001600160401b03167f49c87cda7a22a30abb60733a70e9787c6607d32928c46528890206fdc06fabce855f0160109054906101000a900463ffffffff168c8a885f015f9054906101000a90046001600160801b03168d8960020160109054906101000a90046001600160401b03166040516125ce969594939291906144f8565b60405180910390a481546001600160801b03165f03612619576125f18988612703565b825463ffffffff91909116600160801b0263ffffffff60801b199091161782555f925061265a565b8154600190839060109061263b908490600160801b900463ffffffff16614407565b92506101000a81548163ffffffff021916908363ffffffff1602179055505b6126648988612703565b825463ffffffff918216600160801b90910490911603611c5257611c4f8a8a8a8a865f6133d8565b6001600160801b031983165f818152600d602090815260408083206001600160801b0386811680865291845282852088865284528285208351808501855290549182168152600160801b90910463ffffffff90811682860152958552600784528285209185529252822054919261216492166136fb565b6001600160801b031982165f9081526007602090815260408083206001600160801b0385168452909152812054610a629063ffffffff166001614407565b335f908152602081905260408120546001146127705760405163ea8e4eb560e01b815260040160405180910390fd5b61277a8787612f6f565b61279757604051631eda274960e21b815260040160405180910390fd5b6127a186866117a4565b63ffffffff168463ffffffff1614846127ba88886117a4565b90916127db57604051632c647e3760e21b8152600401610b07929190614423565b5050506001600160801b031985165f908152600a602090815260408083206001600160801b03888116855292529091205481169083168110156128315760405163776a3aa960e11b815260040160405180910390fd5b5f836001600160801b03161161285a5760405163035a9e4760e11b815260040160405180910390fd5b6001600160801b03198681165f8181526009602090815260408083206001600160801b038b811680865291845282852063ffffffff8c1686528452828520600160801b8b8316810290981689831617815560018101805483168b841690990298909817909755948452600a83528184209084529091528120805487939192916128e59185911661446e565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508382612915919061446e565b6001600160801b031988165f8181526007602090815260408083206001600160801b038c811680865291845293829020805463ffffffff60201b1916600160201b63ffffffff8e169081029190911790915582519081528a85169381019390935292851690820152929450916001600160401b038b16907f679cd78fb2cbc9b1fa61043bb803ac3d5a5a8e0dd7aaa5a94e8bc5721dd2b8aa906060015b60405180910390a4509695505050505050565b335f908152602081905260409020546001146129f45760405163ea8e4eb560e01b815260040160405180910390fd5b6129fe8383612f6f565b612a1b57604051631eda274960e21b815260040160405180910390fd5b6001600160801b031982165f818152600360205260409081902080546001600160801b03858116600160801b02911617815590519091906001600160401b038616907f870617e0cf43c45abe8ec9d49e4f116c6c53d5412d17476212c2db8b0913141690612a8a908690613e2c565b60405180910390a350505050565b335f9081526020819052604081205481908190600114612acb5760405163ea8e4eb560e01b815260040160405180910390fd5b612ad58888612f6f565b612af257604051631eda274960e21b815260040160405180910390fd5b6001600160801b031987165f9081526007602090815260408083206001600160801b038a16845290915290205463ffffffff9081169086161115612b49576040516386d1007760e01b815260040160405180910390fd5b612b538787610a1d565b63ffffffff168563ffffffff161485612b6c8989610a1d565b9091612b8d57604051632c647e3760e21b8152600401610b07929190614423565b50506001600160801b03198088165f9081526008602090815260408083206001600160801b038b8116855290835281842063ffffffff8b168552909252909120600281018054928816929093168217909255612be89061329c565b612bf2575f612d3e565b8054604051630274be6d60e21b8152612d3e91600160801b90046001600160801b0316907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906309d2f9b490612c55908c90600401613e2c565b602060405180830381865afa158015612c70573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c94919061443a565b604051600162fe590960e01b031981526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ff01a6f790612ce3908f9060040161445a565b602060405180830381865afa158015612cfe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d22919061443a565b6001850154600160801b90046001600160801b0316895f6132aa565b9350612d49426132b9565b600282018054600160801b600160c01b031916600160801b6001600160401b039384168102919091179091556001600160801b03198a165f8181526007602090815260408083206001600160801b038e8116808652919093529220805463ffffffff60401b1916600160401b63ffffffff8e1602179055855460018701549085900482169850808216975091949293928e16927f75d54fc68ce51f85af6cc4bc67a5d7d3267296e63539b2d428743a1a8a8380de928c928c92612e0d92041661329c565b612e17575f612e3e565b60028701546001880154612e3e916001600160801b0390811691600160801b9004166132e6565b8a60405161139f949392919061448d565b335f90815260208190526040812054600114612e7e5760405163ea8e4eb560e01b815260040160405180910390fd5b612e8787610e0d565b6001600160401b0388165f908152600260205260408120805492935090918290612eb69063ffffffff166145c3565b825463ffffffff8083166101009490940a93840293021916919091179091556001600160401b0389165f9081526005602090815260408083206001600160801b0319871684529091529020805460ff191660011790559050612f1c8288888888886135b2565b8063ffffffff16826001600160801b031916896001600160401b03167fbbd56df32f5dff1bd3d121e1d899391d578077964dcda006d45771892e71eda68a8a8a8a8a6040516129b29594939291906145e7565b6001600160401b0382165f9081526005602090815260408083206001600160801b03198516845290915290205460ff1692915050565b5f612fb3858585855f613749565b95945050505050565b5f612fdd63ffffffff8316600160401b600160801b03604086901b166144bc565b60801b9392505050565b5f8080836001811115612ffc57612ffc614620565b1461303a576001600160801b031988165f908152600c602090815260408083206001600160801b03881684528252808320888452909152902061306f565b6001600160801b031988165f908152600d602090815260408083206001600160801b0388168452825280832088845290915290205b90505f8084600181111561308557613085614620565b146130c3576001600160801b031989165f908152600e602090815260408083206001600160801b0389168452825280832089845290915290206130f8565b6001600160801b031989165f908152600f602090815260408083206001600160801b0389168452825280832089845290915290205b905061310b8a8a8a8a8a8a88888c6137b6565b1561311a575f92505050613267565b866131255787613127565b5f5b9250866131495781546131449089906001600160801b031661446e565b61315f565b815461315f9089906001600160801b03166144bc565b82546001600160801b0319166001600160801b03919091161782555f84600181111561318d5761318d614620565b146131a15761319c89866117a4565b6131ab565b6131ab8986612703565b825463ffffffff91909116600160801b0263ffffffff60801b199091161782555f8460018111156131de576131de614620565b036132265760408051808201909152815460ff81161515825261010090046001600160801b03166020820152613221908b908b908b908b908b908b908990613aba565b613264565b60408051808201909152815460ff81161515825261010090046001600160801b03166020820152613264908b908b908b908b908b908b908990613ba2565b50505b979650505050505050565b5f612164611a17856001600160801b0316856001600160801b0316670de0b6b3a764000086613c51565b6001600160801b0316151590565b5f613267878787878787613ca0565b5f6001600160401b038211156132e25760405163397df9e960e21b815260040160405180910390fd5b5090565b5f610a628383613d42565b5f80805f19858709858702925082811083820303915050805f036133285783828161331e5761331e614634565b0492505050612167565b80841161334857604051637ee8242b60e01b815260040160405180910390fd5b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f6001600160801b038211156132e25760405163e999826d60e01b815260040160405180910390fd5b5f80808360018111156133ed576133ed614620565b1461342b576001600160801b031987165f908152600e602090815260408083206001600160801b038916845282528083208984529091529020613460565b6001600160801b031987165f908152600f602090815260408083206001600160801b0389168452825280832089845290915290205b80549091505f9060ff1661348357815461010090046001600160801b031661348f565b84546001600160801b03165b825490915060ff16156134d057815485546134bb916001600160801b03610100909104811691166144bc565b85546001600160801b0319168655925061351a565b815485546001600160801b0361010090920482169187915f916134f5918591166144bc565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b5f84600181111561352d5761352d614620565b03613568578154604080518082019091525f8082526020820152613563918b918b91859160ff90911615908c908c908c90613aba565b613599565b8154604080518082019091525f8082526020820152613599918b918b91859160ff90911615908c908c908c90613ba2565b5080546001600160881b03191690559695505050505050565b8380158015906135c3575060808111155b6135e057604051637a08c50b60e01b815260040160405180910390fd5b8280158015906135f1575060208111155b61360e576040516314ec8c2560e21b815260040160405180910390fd5b6001600160801b031988165f908152600460205260409020831580156136375750600281015415155b8061364e5750831580159061364e57506002810154155b61366b576040516381e69d9b60e01b815260040160405180910390fd5b831580159061367c57506002810154155b156136d3575f8481526001602052604090205460ff16156136b057604051633ca87f7960e21b815260040160405180910390fd5b5f848152600160208190526040909120805460ff19169091179055600281018490555b806136df888a836146a8565b50600181016136ef8688836146a8565b50505050505050505050565b81515f906001600160801b0316158061372357508163ffffffff16836020015163ffffffff16115b1561372f57505f610a65565b602083015161373e9083614761565b610a62906001614407565b5f8360ff168560ff16036137755761376e611a176001600160801b0385168885613d6b565b9050612fb3565b610f37611a176001600160801b03851661379087600a614860565b61379a908a61486e565b6137a560128a614885565b6137b090600a614860565b86613c51565b5f80808360018111156137cb576137cb614620565b146137df576137da8a876117a4565b6137e9565b6137e98a87612703565b6040805180820190915286546001600160801b0381168252600160801b900463ffffffff1660208201529091506138209082613d89565b1561382e575f915050613aad565b835460ff16801561384757505f896001600160801b0316115b1561386557604051637643c0f960e01b815260040160405180910390fd5b8761387a57835460ff191660011784556138c1565b83548990859060019061389c90849061010090046001600160801b03166144bc565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b5f8360018111156138d4576138d4614620565b036139c2575f600b5f8c6001600160801b0319166001600160801b03191681526020019081526020015f205f886001600160801b03166001600160801b031681526020019081526020015f205f9054906101000a90046001600160801b03169050866001600160801b03168b6001600160801b0319168d6001600160401b03165f5160206148f05f395f51905f52858c8b5f015f9054906101000a90046001600160801b0316878c5f0160019054906101000a90046001600160801b03168d5f015f9054906101000a900460ff166040516139b49695949392919061489e565b60405180910390a450613aa7565b5f600a5f8c6001600160801b0319166001600160801b03191681526020019081526020015f205f886001600160801b03166001600160801b031681526020019081526020015f205f9054906101000a90046001600160801b03169050866001600160801b03168b6001600160801b0319168d6001600160401b03165f5160206149105f395f51905f52858c8b5f015f9054906101000a90046001600160801b0316878c5f0160019054906101000a90046001600160801b03168d5f015f9054906101000a900460ff16604051613a9d9695949392919061489e565b60405180910390a4505b60019150505b9998505050505050505050565b6001600160801b031987165f908152600b602090815260408083206001600160801b0387811685529252909120541685613afd57613af8878261446e565b613b07565b613b0787826144bc565b6001600160801b03198981165f818152600b602090815260408083206001600160801b038b8116808652919093529220805490941690851617909255919250906001600160401b038b165f5160206148f05f395f51905f52613b698c89612703565b875460208801518851604051613b8f94938e936001600160801b03909116928b9261489e565b60405180910390a4505050505050505050565b6001600160801b031987165f908152600a602090815260408083206001600160801b0387811685529252909120541685613be557613be0878261446e565b613bef565b613bef87826144bc565b6001600160801b03198981165f818152600a602090815260408083206001600160801b038b8116808652919093529220805490941690851617909255919250906001600160401b038b165f5160206149105f395f51905f52613b698c896117a4565b5f5f613c5e8686866132f1565b90506001836002811115613c7457613c74614620565b148015613c9057505f8480613c8b57613c8b614634565b868809115b15612fb357610f376001826148dc565b5f613cb3836001600160801b031661329c565b613cfd5760405162461bcd60e51b815260206004820152601b60248201527a50726963696e674c69622f6469766973696f6e2d62792d7a65726f60281b6044820152606401610b07565b613267611a176001600160801b03861689613d1989600a614860565b613d23919061486e565b6001600160801b038716613d388b600a614860565b6137b0919061486e565b5f610a62611a17846001600160801b0316670de0b6b3a7640000856001600160801b03166132f1565b5f612164846001600160801b031684670de0b6b3a764000085613c51565b5f60018263ffffffff16111580613da8575082516001600160801b0316155b80610a6257505060209091015163ffffffff9182169116101590565b80356001600160801b031981168114613ddb575f5ffd5b919050565b6001600160801b0381168114613df4575f5ffd5b50565b5f5f60408385031215613e08575f5ffd5b613e1183613dc4565b91506020830135613e2181613de0565b809150509250929050565b6001600160801b0391909116815260200190565b5f5f5f60608486031215613e52575f5ffd5b613e5b84613dc4565b92506020840135613e6b81613de0565b929592945050506040919091013590565b80356001600160401b0381168114613ddb575f5ffd5b803563ffffffff81168114613ddb575f5ffd5b5f5f5f5f5f5f60c08789031215613eba575f5ffd5b613ec387613e7c565b9550613ed160208801613dc4565b94506040870135613ee181613de0565b9350613eef60608801613e92565b92506080870135613eff81613de0565b915060a0870135613f0f81613de0565b809150509295509295509295565b5f60208284031215613f2d575f5ffd5b610a6282613e7c565b5f5f5f5f60808587031215613f49575f5ffd5b613f5285613e7c565b9350613f6060208601613dc4565b9250604085013591506060850135613f7781613de0565b939692955090935050565b5f5f60408385031215613f93575f5ffd5b613f9c83613e7c565b9150613faa60208401613e92565b90509250929050565b5f5f5f5f5f60a08688031215613fc7575f5ffd5b613fd086613e7c565b9450613fde60208701613dc4565b93506040860135613fee81613de0565b9250613ffc60608701613e92565b9150608086013561400c81613de0565b809150509295509295909350565b5f5f5f6060848603121561402c575f5ffd5b61403584613dc4565b9250602084013561404581613de0565b915061405360408501613e92565b90509250925092565b803561ffff81168114613ddb575f5ffd5b5f5f5f5f5f60a08688031215614081575f5ffd5b61408a8661405c565b945061409860208701613e7c565b93506140a660408701613dc4565b925060608601356140b681613de0565b91506080860135801515811461400c575f5ffd5b5f5f604083850312156140db575f5ffd5b6140e483613dc4565b9150613faa6020840161405c565b5f60208284031215614102575f5ffd5b81356001600160a01b0381168114612167575f5ffd5b5f60208284031215614128575f5ffd5b610a6282613dc4565b5f5f5f5f5f60a08688031215614145575f5ffd5b61414e86613e7c565b945061415c60208701613dc4565b9350604086013561416c81613de0565b925060608601359150608086013561400c81613de0565b5f5f83601f840112614193575f5ffd5b5081356001600160401b038111156141a9575f5ffd5b6020830191508360208285010111156141c0575f5ffd5b9250929050565b5f5f5f5f5f5f608087890312156141dc575f5ffd5b6141e587613e7c565b95506141f360208801613dc4565b945060408701356001600160401b0381111561420d575f5ffd5b61421989828a01614183565b90955093505060608701356001600160401b03811115614237575f5ffd5b61424389828a01614183565b979a9699509497509295939492505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6142956060830186614255565b82810360208401526142a78186614255565b915050826040830152949350505050565b5f5f5f606084860312156142ca575f5ffd5b6142d384613dc4565b92506020840135915060408401356142ea81613de0565b809150509250925092565b5f5f5f60608486031215614307575f5ffd5b61431084613e7c565b925061431e60208501613dc4565b915060408401356142ea81613de0565b5f6020828403121561433e575f5ffd5b5035919050565b5f5f5f5f5f5f6080878903121561435a575f5ffd5b61436387613e7c565b955060208701356001600160401b0381111561437d575f5ffd5b61438989828a01614183565b90965094505060408701356001600160401b038111156143a7575f5ffd5b6143b389828a01614183565b979a9699509497949695606090950135949350505050565b5f5f604083850312156143dc575f5ffd5b6143e583613e7c565b9150613faa60208401613dc4565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff8181168382160190811115610a6557610a656143f3565b63ffffffff92831681529116602082015260400190565b5f6020828403121561444a575f5ffd5b815160ff81168114612167575f5ffd5b6001600160401b0391909116815260200190565b6001600160801b038281168282160390811115610a6557610a656143f3565b63ffffffff9490941684526001600160801b039283166020850152908216604084015216606082015260800190565b6001600160801b038181168382160190811115610a6557610a656143f3565b61ffff9290921682526001600160801b0316602082015260400190565b63ffffffff96909616865260208601949094526001600160801b03928316604086015290821660608501521660808301526001600160401b031660a082015260c00190565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f61457860408301868861453d565b828103602084015261326781858761453d565b600181811c9082168061459f57607f821691505b6020821081036145bd57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f63ffffffff821663ffffffff81036145de576145de6143f3565b60010192915050565b606081525f6145fa60608301878961453d565b828103602084015261460d81868861453d565b9150508260408301529695505050505050565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b601f8211156146a357805f5260205f20601f840160051c810160208510156146815750805b601f840160051c820191505b818110156146a0575f815560010161468d565b50505b505050565b6001600160401b038311156146bf576146bf614648565b6146d3836146cd835461458b565b8361465c565b5f601f841160018114614704575f85156146ed5750838201355b5f19600387901b1c1916600186901b1783556146a0565b5f83815260208120601f198716915b828110156147335786850135825560209485019460019092019101614713565b508682101561474f575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b63ffffffff8281168282160390811115610a6557610a656143f3565b6001815b60018411156147b85780850481111561479c5761479c6143f3565b60018416156147aa57908102905b60019390931c928002614781565b935093915050565b5f826147ce57506001610a65565b816147da57505f610a65565b81600181146147f057600281146147fa57614816565b6001915050610a65565b60ff84111561480b5761480b6143f3565b50506001821b610a65565b5060208310610133831016604e8410600b8410161715614839575081810a610a65565b6148455f19848461477d565b805f1904821115614858576148586143f3565b029392505050565b5f610a6260ff8416836147c0565b8082028115828204841417610a6557610a656143f3565b60ff8181168382160190811115610a6557610a656143f3565b63ffffffff96909616865260208601949094526001600160801b0392831660408601529082166060850152166080830152151560a082015260c00190565b80820180821115610a6557610a656143f356fe1f5a5e518a04d4ae04df91bdcdfc726fd04628d7968eb87c8a177f55336765ff688670c8bdbd011a5a7703624480229795dd54b1ead47cb9a66061fa8b2e0b7aa264697066735822122037736688b1e69a7f3366472d63f827c0884c18babd2501e7b3530c0cf1c1ba3864736f6c634300081c003300000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb0000000000000000000000005f3f8ea3b54bff7795de7754866e0eac52e0881d
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610218575f3560e01c80630162c7511461021c578063029dbcfe1461024957806305a3aff91461028957806314e2acc9146102f55780631577b7a1146103285780631633f3c11461035457806317ef047a146103675780631ac1e1d51461037a578063293d4b84146103b75780632c1917ee1461046e5780633ba3d070146104d05780633cc7116b146104f557806346bfcc8f1461050a5780634d61dc291461051d5780634e1ea2cd14610560578063516a6a74146105df57806365fae35e146106125780636787053c146106255780637315cf5814610638578063790b56ce1461066b5780637dea42b31461067e57806386a672dd146106c65780638a6fd02a146107325780638baa4083146107655780638bd95b44146107785780638c34e9331461078b5780639b884cd5146107ce5780639c52a7f1146107e15780639ea3d094146107f4578063a3bfe16814610816578063a822014914610829578063aa903d731461083c578063bec24d911461084f578063bf353dbb14610862578063c4035bd01461088f578063c4d49aa3146108a2578063c7ade5c0146108b5578063c88854a3146108e8578063d0d4133114610927578063db254ea71461093a578063ddcdfa3414610982578063e6d283a614610995578063ec762bfe146109b7578063efdd0d0e146109ca578063fb868432146109dd578063fbd2ab3e14610a0a575b5f5ffd5b61022f61022a366004613df7565b610a1d565b60405163ffffffff90911681526020015b60405180910390f35b61027c610257366004613df7565b600a60209081525f92835260408084209091529082529020546001600160801b031681565b6040516102409190613e2c565b6102d1610297366004613e40565b600c60209081525f93845260408085208252928452828420905282529020546001600160801b03811690600160801b900463ffffffff1682565b604080516001600160801b03909316835263ffffffff909116602083015201610240565b610308610303366004613ea5565b610a6b565b604080516001600160801b03938416815292909116602083015201610240565b61033b610336366004613f1d565b610e0d565b6040516001600160801b03199091168152602001610240565b61027c610362366004613f36565b610e41565b61033b610375366004613f82565b610f41565b61038d610388366004613fb3565b610f4c565b604080516001600160801b0394851681529284166020840152921691810191909152606001610240565b6104236103c536600461401a565b600960209081525f93845260408085208252928452828420905282529020805460018201546002909201546001600160801b0380831693600160801b938490048216938282169391819004831692821691046001600160401b031686565b604080516001600160801b039788168152958716602087015293861693850193909352908416606084015290921660808201526001600160401b0390911660a082015260c001610240565b6104b161047c366004613e40565b600f60209081525f938452604080852082529284528284209052825290205460ff81169061010090046001600160801b031682565b6040805192151583526001600160801b03909116602083015201610240565b61022f6104de366004613f1d565b60026020525f908152604090205463ffffffff1681565b61050861050336600461406d565b6113b3565b005b61027c610518366004613f36565b611668565b61055061052b366004613e40565b601060209081525f938452604080852082529284528284209052825290205460ff1681565b6040519015158152602001610240565b6105af61056e366004613df7565b600760209081525f928352604080842090915290825290205463ffffffff80821691600160201b8104821691600160401b8204811691600160601b90041684565b6040805163ffffffff95861681529385166020850152918416918301919091529091166060820152608001610240565b61027c6105ed3660046140ca565b600660209081525f92835260408084209091529082529020546001600160801b031681565b6105086106203660046140f2565b611731565b61022f610633366004613df7565b6117a4565b610308610646366004614118565b60036020525f90815260409020546001600160801b0380821691600160801b90041682565b610508610679366004614131565b6117e9565b61069161068c366004613f36565b611857565b60405161024094939291906001600160801b039485168152928416602084015292166040820152901515606082015260800190565b6104236106d436600461401a565b600860209081525f93845260408085208252928452828420905282529020805460018201546002909201546001600160801b0380831693600160801b938490048216938282169391819004831692821691046001600160401b031686565b610550610740366004613e40565b601160209081525f938452604080852082529284528284209052825290205460ff1681565b610508610773366004614131565b611c5f565b6105086107863660046141c7565b611cc6565b6104b1610799366004613e40565b600e60209081525f938452604080852082529284528284209052825290205460ff81169061010090046001600160801b031682565b61027c6107dc366004613f36565b611d84565b6105086107ef3660046140f2565b611e50565b610807610802366004614118565b611ec2565b60405161024093929190614283565b61027c610824366004613f36565b611fef565b61022f6108373660046142b8565b6120e6565b61022f61084a366004613df7565b61216e565b61069161085d366004613f36565b6121b3565b6108816108703660046140f2565b5f6020819052908152604090205481565b604051908152602001610240565b61022f61089d3660046142b8565b61268c565b61022f6108b0366004613df7565b612703565b61027c6108c3366004613df7565b600b60209081525f92835260408084209091529082529020546001600160801b031681565b61090f7f00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb81565b6040516001600160a01b039091168152602001610240565b61027c610935366004613ea5565b612741565b6102d1610948366004613e40565b600d60209081525f93845260408085208252928452828420905282529020546001600160801b03811690600160801b900463ffffffff1682565b6105086109903660046142f5565b6129c5565b6105506109a336600461432e565b60016020525f908152604090205460ff1681565b61038d6109c5366004613fb3565b612a98565b61033b6109d8366004614345565b612e4f565b6105506109eb3660046143cb565b600560209081525f928352604080842090915290825290205460ff1681565b610550610a183660046143cb565b612f6f565b6001600160801b031982165f9081526007602090815260408083206001600160801b0385168452909152812054610a6290600160401b900463ffffffff166001614407565b90505b92915050565b335f908152602081905260408120548190600114610a9c5760405163ea8e4eb560e01b815260040160405180910390fd5b610aa68888612f6f565b610ac357604051631eda274960e21b815260040160405180910390fd5b610acd8787612703565b63ffffffff168563ffffffff161485610ae68989612703565b9091610b1057604051632c647e3760e21b8152600401610b07929190614423565b60405180910390fd5b50506001600160801b031987165f908152600b602090815260408083206001600160801b038a81168552925290912054811692508416821015610b665760405163776a3aa960e11b815260040160405180910390fd5b5f846001600160801b031611610b8f5760405163035a9e4760e11b815260040160405180910390fd5b610cbb846001600160801b03167f00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb6001600160a01b03166309d2f9b4896040518263ffffffff1660e01b8152600401610be89190613e2c565b602060405180830381865afa158015610c03573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c27919061443a565b604051600162fe590960e01b031981526001600160a01b037f00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb169063ff01a6f790610c76908e9060040161445a565b602060405180830381865afa158015610c91573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cb5919061443a565b86612fa5565b6001600160801b03198089165f8181526008602090815260408083206001600160801b038d811680865291845282852063ffffffff8e16865284528285208a82168d8316600160801b9081029099161781558b8216909702818916176001880155948452600b8352818420908452909152812080549495509293889392610d449185911661446e565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508483610d74919061446e565b6001600160801b031989165f8181526007602090815260408083206001600160801b038d16808552925291829020805463ffffffff191663ffffffff8c161790559051929550916001600160401b038c16907f1785217365be01fea67dbce22680b382886fe6a3a22156830b3cda5823a42a8e90610df9908b9088908c908b9061448d565b60405180910390a450965096945050505050565b6001600160401b0381165f90815260026020526040812054610a65908390610e3c9063ffffffff166001614407565b612fbc565b335f90815260208190526040812054600114610e705760405163ea8e4eb560e01b815260040160405180910390fd5b610e7a8585612f6f565b610e9757604051631eda274960e21b815260040160405180910390fd5b6001600160801b031984165f9081526010602090815260408083206001600160801b0386168452825280832086845290915290205460ff16610eec57604051635fb581dd60e01b815260040160405180910390fd5b6001600160801b031984165f908152600d602090815260408083206001600160801b0386811685529083528184208785529092528220541690610f3790879087908490888882612fe7565b9695505050505050565b5f610a628383612fbc565b335f9081526020819052604081205481908190600114610f7f5760405163ea8e4eb560e01b815260040160405180910390fd5b610f898888612f6f565b610fa657604051631eda274960e21b815260040160405180910390fd5b6001600160801b031987165f9081526007602090815260408083206001600160801b038a16845290915290205463ffffffff600160201b90910481169086161115611004576040516386d1007760e01b815260040160405180910390fd5b61100e878761216e565b63ffffffff168563ffffffff161485611027898961216e565b909161104857604051632c647e3760e21b8152600401610b07929190614423565b50506001600160801b03198088165f9081526009602090815260408083206001600160801b038b8116855290835281842063ffffffff808c16865293529083206002810180548a8416961686179055805490946110b4949093600160801b909204909216919061327216565b60018201549092506110d590600160801b90046001600160801b031661329c565b6110df575f611234565b8054604051600162fe590960e01b0319815261123491600160801b90046001600160801b0316907f00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb6001600160a01b03169063ff01a6f790611145908e9060040161445a565b602060405180830381865afa158015611160573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611184919061443a565b604051630274be6d60e21b81526001600160a01b037f00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb16906309d2f9b4906111d0908d90600401613e2c565b602060405180830381865afa1580156111eb573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061120f919061443a565b600285015460018601546001600160801b0391821691600160801b909104165f6132aa565b81546001830180546001600160801b0319166001600160801b0384811691909117909155600160801b909104169450925061126e426132b9565b600282018054600160801b600160c01b031916600160801b6001600160401b039384168102919091179091556001600160801b03198a165f8181526007602090815260408083206001600160801b038e8116808652919093529220805463ffffffff60601b1916600160601b63ffffffff8e1602179055600186015491949293928e16927f14f07afe7ac79d02cc585b7f76d4d9687e82b16083b19e225a2fde74b32bf36e928c928c9261132392041661329c565b61132d575f611354565b60028701546001880154611354916001600160801b0390811691600160801b9004166132e6565b87546040805163ffffffff90951685526001600160801b03938416602086015291831691840191909152600160801b9004811660608301528881166080830152871660a082015260c0015b60405180910390a450955095509592505050565b335f908152602081905260409020546001146113e25760405163ea8e4eb560e01b815260040160405180910390fd5b6113ec8484612f6f565b61140957604051631eda274960e21b815260040160405180910390fd5b808061144857506001600160801b031983165f90815260066020908152604080832061ffff891684529091529020546001600160801b03808416911610155b61146557604051635fe755ed60e01b815260040160405180910390fd5b5f8161149d576001600160801b031984165f908152600360205260409020546114989084906001600160801b031661446e565b6114ca565b6001600160801b031984165f908152600360205260409020546114ca9084906001600160801b03166144bc565b6001600160801b03198581165f90815260036020526040812080549092166001600160801b038416179091559091508261153f576001600160801b031985165f90815260066020908152604080832061ffff8b16845290915290205461153a9085906001600160801b031661446e565b61157b565b6001600160801b031985165f90815260066020908152604080832061ffff8b16845290915290205461157b9085906001600160801b03166144bc565b6001600160801b03198681165f90815260066020908152604080832061ffff8d168452909152902080549091166001600160801b0383161790559050821561161057846001600160801b031916866001600160401b03167f2c63f350e031a7945cf5c5d46ff2bfb9dbf69c9b401dff10c60d6bb1c4d0687489876040516116039291906144db565b60405180910390a361165f565b846001600160801b031916866001600160401b03167fc2f94e30444446144c04ae7a5e046b226a3640ea83c2c7cf1a0a4fee4be36ff089876040516116569291906144db565b60405180910390a35b50505050505050565b335f908152602081905260408120546001146116975760405163ea8e4eb560e01b815260040160405180910390fd5b6116a18585612f6f565b6116be57604051631eda274960e21b815260040160405180910390fd5b6001600160801b031984165f8181526010602090815260408083206001600160801b038781168086529184528285208986528452828520805460ff19166001179055948452600d8352818420908452825280832087845290915281205490911690610f3790879087908490888882612fe7565b335f908152602081905260409020546001146117605760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b6001600160801b031982165f9081526007602090815260408083206001600160801b0385168452909152812054610a6290600160201b900463ffffffff166001614407565b335f908152602081905260409020546001146118185760405163ea8e4eb560e01b815260040160405180910390fd5b6118228585612f6f565b61183f57604051631eda274960e21b815260040160405180910390fd5b61184f858585600186865f612fe7565b505050505050565b335f9081526020819052604081205481908190819060011461188c5760405163ea8e4eb560e01b815260040160405180910390fd5b6118968888612f6f565b6118b357604051631eda274960e21b815260040160405180910390fd5b6001600160801b031987165f908152600c602090815260408083206001600160801b0389811685529083528184208a8552909252909120805490911661190c5760405163484a885b60e01b815260040160405180910390fd5b6001600160801b031988165f9081526007602090815260408083206001600160801b038a1684529091529020548154600160601b90910463ffffffff908116600160801b90920416111561197357604051639aac3e0b60e01b815260040160405180910390fd5b6001600160801b031988165f8181526007602090815260408083206001600160801b038b81168086529184528285205487549686526009855283862092865291845282852063ffffffff600160801b97889004811680885291909552929094208054600160601b9092049093169091109550909290041615611a215780548254611a1c91611a17916001600160801b0390811691600160801b8104821691166132f1565b6133af565b611a23565b5f5b94506001600160801b03851615611af9576001810154611a5290600160801b90046001600160801b031661329c565b611a5c575f611ab5565b611ab5856001600160801b03167f00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb6001600160a01b031663ff01a6f78d6040518263ffffffff1660e01b8152600401611145919061445a565b8254909650859083905f90611ad49084906001600160801b031661446e565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b866001600160801b0316896001600160801b0319168b6001600160401b03167fbaedde181510aaa5fcaded7a64ddd81c51a9b07b5ed0209b6e3a92801c93959e855f0160109054906101000a900463ffffffff168c8a885f015f9054906101000a90046001600160801b03168d8960020160109054906101000a90046001600160401b0316604051611b90969594939291906144f8565b60405180910390a481546001600160801b03165f03611bdb57611bb389886117a4565b825463ffffffff91909116600160801b0263ffffffff60801b199091161782555f9250611c1c565b81546001908390601090611bfd908490600160801b900463ffffffff16614407565b92506101000a81548163ffffffff021916908363ffffffff1602179055505b611c2689886117a4565b825463ffffffff918216600160801b90910490911603611c5257611c4f8a8a8a8a8660016133d8565b93505b5050945094509450949050565b335f90815260208190526040902054600114611c8e5760405163ea8e4eb560e01b815260040160405180910390fd5b611c988585612f6f565b611cb557604051631eda274960e21b815260040160405180910390fd5b61184f858585600186866001612fe7565b335f90815260208190526040902054600114611cf55760405163ea8e4eb560e01b815260040160405180910390fd5b611cff8686612f6f565b611d1c57604051631eda274960e21b815260040160405180910390fd5b611d2a85858585855f6135b2565b846001600160801b031916866001600160401b03167f8c0eec6877ffbfd88a45283fadb04a776dc75b31282041dcbc782bb24d3c4a7186868686604051611d749493929190614565565b60405180910390a3505050505050565b335f90815260208190526040812054600114611db35760405163ea8e4eb560e01b815260040160405180910390fd5b611dbd8585612f6f565b611dda57604051631eda274960e21b815260040160405180910390fd5b6001600160801b031984165f8181526011602090815260408083206001600160801b038781168086529184528285208986528452828520805460ff19166001908117909155958552600c84528285209185529083528184208885529092528220541691610f379188918891859189908990612fe7565b335f90815260208190526040902054600114611e7f5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b60046020525f9081526040902080548190611edc9061458b565b80601f0160208091040260200160405190810160405280929190818152602001828054611f089061458b565b8015611f535780601f10611f2a57610100808354040283529160200191611f53565b820191905f5260205f20905b815481529060010190602001808311611f3657829003601f168201915b505050505090806001018054611f689061458b565b80601f0160208091040260200160405190810160405280929190818152602001828054611f949061458b565b8015611fdf5780601f10611fb657610100808354040283529160200191611fdf565b820191905f5260205f20905b815481529060010190602001808311611fc257829003601f168201915b5050505050908060020154905083565b335f9081526020819052604081205460011461201e5760405163ea8e4eb560e01b815260040160405180910390fd5b6120288585612f6f565b61204557604051631eda274960e21b815260040160405180910390fd5b6001600160801b031984165f9081526011602090815260408083206001600160801b0386168452825280832086845290915290205460ff1661209a57604051635fb581dd60e01b815260040160405180910390fd5b6001600160801b031984165f908152600c602090815260408083206001600160801b0386811685529083528184208785529092528220541690610f379087908790849088886001612fe7565b6001600160801b031983165f818152600c602090815260408083206001600160801b0386811680865291845282852088865284528285208351808501855290549182168152600160801b90910463ffffffff90811682860152958552600784528285209185529252822054919261216492600160201b9004166136fb565b90505b9392505050565b6001600160801b031982165f9081526007602090815260408083206001600160801b0385168452909152812054610a6290600160601b900463ffffffff166001614407565b335f908152602081905260408120548190819081906001146121e85760405163ea8e4eb560e01b815260040160405180910390fd5b6121f28888612f6f565b61220f57604051631eda274960e21b815260040160405180910390fd5b6001600160801b031987165f908152600d602090815260408083206001600160801b0389811685529083528184208a855290925290912080549091166122685760405163484a885b60e01b815260040160405180910390fd5b6001600160801b031988165f9081526007602090815260408083206001600160801b038a1684529091529020548154600160401b90910463ffffffff908116600160801b9092041611156122cf57604051638691a7e760e01b815260040160405180910390fd5b6001600160801b031988165f8181526007602090815260408083206001600160801b038b81168086529184528285205487549686526008855283862092865291845282852063ffffffff600160801b97889004811680885291909552929094208054600160401b9092049093169091109550909290041615612378578054825461237391611a17916001600160801b0390811691600160801b8104821691166132f1565b61237a565b5f5b94506001600160801b038516156125375760028101546123a2906001600160801b031661329c565b6123ac575f6124f3565b6124f3856001600160801b03167f00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb6001600160a01b03166309d2f9b48a6040518263ffffffff1660e01b81526004016124059190613e2c565b602060405180830381865afa158015612420573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612444919061443a565b7f00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb6001600160a01b031663ff01a6f78e6040518263ffffffff1660e01b8152600401612490919061445a565b602060405180830381865afa1580156124ab573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124cf919061443a565b600185015460028601546001600160801b03600160801b909204821691165f6132aa565b8254909650859083905f906125129084906001600160801b031661446e565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b866001600160801b0316896001600160801b0319168b6001600160401b03167f49c87cda7a22a30abb60733a70e9787c6607d32928c46528890206fdc06fabce855f0160109054906101000a900463ffffffff168c8a885f015f9054906101000a90046001600160801b03168d8960020160109054906101000a90046001600160401b03166040516125ce969594939291906144f8565b60405180910390a481546001600160801b03165f03612619576125f18988612703565b825463ffffffff91909116600160801b0263ffffffff60801b199091161782555f925061265a565b8154600190839060109061263b908490600160801b900463ffffffff16614407565b92506101000a81548163ffffffff021916908363ffffffff1602179055505b6126648988612703565b825463ffffffff918216600160801b90910490911603611c5257611c4f8a8a8a8a865f6133d8565b6001600160801b031983165f818152600d602090815260408083206001600160801b0386811680865291845282852088865284528285208351808501855290549182168152600160801b90910463ffffffff90811682860152958552600784528285209185529252822054919261216492166136fb565b6001600160801b031982165f9081526007602090815260408083206001600160801b0385168452909152812054610a629063ffffffff166001614407565b335f908152602081905260408120546001146127705760405163ea8e4eb560e01b815260040160405180910390fd5b61277a8787612f6f565b61279757604051631eda274960e21b815260040160405180910390fd5b6127a186866117a4565b63ffffffff168463ffffffff1614846127ba88886117a4565b90916127db57604051632c647e3760e21b8152600401610b07929190614423565b5050506001600160801b031985165f908152600a602090815260408083206001600160801b03888116855292529091205481169083168110156128315760405163776a3aa960e11b815260040160405180910390fd5b5f836001600160801b03161161285a5760405163035a9e4760e11b815260040160405180910390fd5b6001600160801b03198681165f8181526009602090815260408083206001600160801b038b811680865291845282852063ffffffff8c1686528452828520600160801b8b8316810290981689831617815560018101805483168b841690990298909817909755948452600a83528184209084529091528120805487939192916128e59185911661446e565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508382612915919061446e565b6001600160801b031988165f8181526007602090815260408083206001600160801b038c811680865291845293829020805463ffffffff60201b1916600160201b63ffffffff8e169081029190911790915582519081528a85169381019390935292851690820152929450916001600160401b038b16907f679cd78fb2cbc9b1fa61043bb803ac3d5a5a8e0dd7aaa5a94e8bc5721dd2b8aa906060015b60405180910390a4509695505050505050565b335f908152602081905260409020546001146129f45760405163ea8e4eb560e01b815260040160405180910390fd5b6129fe8383612f6f565b612a1b57604051631eda274960e21b815260040160405180910390fd5b6001600160801b031982165f818152600360205260409081902080546001600160801b03858116600160801b02911617815590519091906001600160401b038616907f870617e0cf43c45abe8ec9d49e4f116c6c53d5412d17476212c2db8b0913141690612a8a908690613e2c565b60405180910390a350505050565b335f9081526020819052604081205481908190600114612acb5760405163ea8e4eb560e01b815260040160405180910390fd5b612ad58888612f6f565b612af257604051631eda274960e21b815260040160405180910390fd5b6001600160801b031987165f9081526007602090815260408083206001600160801b038a16845290915290205463ffffffff9081169086161115612b49576040516386d1007760e01b815260040160405180910390fd5b612b538787610a1d565b63ffffffff168563ffffffff161485612b6c8989610a1d565b9091612b8d57604051632c647e3760e21b8152600401610b07929190614423565b50506001600160801b03198088165f9081526008602090815260408083206001600160801b038b8116855290835281842063ffffffff8b168552909252909120600281018054928816929093168217909255612be89061329c565b612bf2575f612d3e565b8054604051630274be6d60e21b8152612d3e91600160801b90046001600160801b0316907f00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb6001600160a01b0316906309d2f9b490612c55908c90600401613e2c565b602060405180830381865afa158015612c70573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c94919061443a565b604051600162fe590960e01b031981526001600160a01b037f00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb169063ff01a6f790612ce3908f9060040161445a565b602060405180830381865afa158015612cfe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d22919061443a565b6001850154600160801b90046001600160801b0316895f6132aa565b9350612d49426132b9565b600282018054600160801b600160c01b031916600160801b6001600160401b039384168102919091179091556001600160801b03198a165f8181526007602090815260408083206001600160801b038e8116808652919093529220805463ffffffff60401b1916600160401b63ffffffff8e1602179055855460018701549085900482169850808216975091949293928e16927f75d54fc68ce51f85af6cc4bc67a5d7d3267296e63539b2d428743a1a8a8380de928c928c92612e0d92041661329c565b612e17575f612e3e565b60028701546001880154612e3e916001600160801b0390811691600160801b9004166132e6565b8a60405161139f949392919061448d565b335f90815260208190526040812054600114612e7e5760405163ea8e4eb560e01b815260040160405180910390fd5b612e8787610e0d565b6001600160401b0388165f908152600260205260408120805492935090918290612eb69063ffffffff166145c3565b825463ffffffff8083166101009490940a93840293021916919091179091556001600160401b0389165f9081526005602090815260408083206001600160801b0319871684529091529020805460ff191660011790559050612f1c8288888888886135b2565b8063ffffffff16826001600160801b031916896001600160401b03167fbbd56df32f5dff1bd3d121e1d899391d578077964dcda006d45771892e71eda68a8a8a8a8a6040516129b29594939291906145e7565b6001600160401b0382165f9081526005602090815260408083206001600160801b03198516845290915290205460ff1692915050565b5f612fb3858585855f613749565b95945050505050565b5f612fdd63ffffffff8316600160401b600160801b03604086901b166144bc565b60801b9392505050565b5f8080836001811115612ffc57612ffc614620565b1461303a576001600160801b031988165f908152600c602090815260408083206001600160801b03881684528252808320888452909152902061306f565b6001600160801b031988165f908152600d602090815260408083206001600160801b0388168452825280832088845290915290205b90505f8084600181111561308557613085614620565b146130c3576001600160801b031989165f908152600e602090815260408083206001600160801b0389168452825280832089845290915290206130f8565b6001600160801b031989165f908152600f602090815260408083206001600160801b0389168452825280832089845290915290205b905061310b8a8a8a8a8a8a88888c6137b6565b1561311a575f92505050613267565b866131255787613127565b5f5b9250866131495781546131449089906001600160801b031661446e565b61315f565b815461315f9089906001600160801b03166144bc565b82546001600160801b0319166001600160801b03919091161782555f84600181111561318d5761318d614620565b146131a15761319c89866117a4565b6131ab565b6131ab8986612703565b825463ffffffff91909116600160801b0263ffffffff60801b199091161782555f8460018111156131de576131de614620565b036132265760408051808201909152815460ff81161515825261010090046001600160801b03166020820152613221908b908b908b908b908b908b908990613aba565b613264565b60408051808201909152815460ff81161515825261010090046001600160801b03166020820152613264908b908b908b908b908b908b908990613ba2565b50505b979650505050505050565b5f612164611a17856001600160801b0316856001600160801b0316670de0b6b3a764000086613c51565b6001600160801b0316151590565b5f613267878787878787613ca0565b5f6001600160401b038211156132e25760405163397df9e960e21b815260040160405180910390fd5b5090565b5f610a628383613d42565b5f80805f19858709858702925082811083820303915050805f036133285783828161331e5761331e614634565b0492505050612167565b80841161334857604051637ee8242b60e01b815260040160405180910390fd5b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f6001600160801b038211156132e25760405163e999826d60e01b815260040160405180910390fd5b5f80808360018111156133ed576133ed614620565b1461342b576001600160801b031987165f908152600e602090815260408083206001600160801b038916845282528083208984529091529020613460565b6001600160801b031987165f908152600f602090815260408083206001600160801b0389168452825280832089845290915290205b80549091505f9060ff1661348357815461010090046001600160801b031661348f565b84546001600160801b03165b825490915060ff16156134d057815485546134bb916001600160801b03610100909104811691166144bc565b85546001600160801b0319168655925061351a565b815485546001600160801b0361010090920482169187915f916134f5918591166144bc565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b5f84600181111561352d5761352d614620565b03613568578154604080518082019091525f8082526020820152613563918b918b91859160ff90911615908c908c908c90613aba565b613599565b8154604080518082019091525f8082526020820152613599918b918b91859160ff90911615908c908c908c90613ba2565b5080546001600160881b03191690559695505050505050565b8380158015906135c3575060808111155b6135e057604051637a08c50b60e01b815260040160405180910390fd5b8280158015906135f1575060208111155b61360e576040516314ec8c2560e21b815260040160405180910390fd5b6001600160801b031988165f908152600460205260409020831580156136375750600281015415155b8061364e5750831580159061364e57506002810154155b61366b576040516381e69d9b60e01b815260040160405180910390fd5b831580159061367c57506002810154155b156136d3575f8481526001602052604090205460ff16156136b057604051633ca87f7960e21b815260040160405180910390fd5b5f848152600160208190526040909120805460ff19169091179055600281018490555b806136df888a836146a8565b50600181016136ef8688836146a8565b50505050505050505050565b81515f906001600160801b0316158061372357508163ffffffff16836020015163ffffffff16115b1561372f57505f610a65565b602083015161373e9083614761565b610a62906001614407565b5f8360ff168560ff16036137755761376e611a176001600160801b0385168885613d6b565b9050612fb3565b610f37611a176001600160801b03851661379087600a614860565b61379a908a61486e565b6137a560128a614885565b6137b090600a614860565b86613c51565b5f80808360018111156137cb576137cb614620565b146137df576137da8a876117a4565b6137e9565b6137e98a87612703565b6040805180820190915286546001600160801b0381168252600160801b900463ffffffff1660208201529091506138209082613d89565b1561382e575f915050613aad565b835460ff16801561384757505f896001600160801b0316115b1561386557604051637643c0f960e01b815260040160405180910390fd5b8761387a57835460ff191660011784556138c1565b83548990859060019061389c90849061010090046001600160801b03166144bc565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b5f8360018111156138d4576138d4614620565b036139c2575f600b5f8c6001600160801b0319166001600160801b03191681526020019081526020015f205f886001600160801b03166001600160801b031681526020019081526020015f205f9054906101000a90046001600160801b03169050866001600160801b03168b6001600160801b0319168d6001600160401b03165f5160206148f05f395f51905f52858c8b5f015f9054906101000a90046001600160801b0316878c5f0160019054906101000a90046001600160801b03168d5f015f9054906101000a900460ff166040516139b49695949392919061489e565b60405180910390a450613aa7565b5f600a5f8c6001600160801b0319166001600160801b03191681526020019081526020015f205f886001600160801b03166001600160801b031681526020019081526020015f205f9054906101000a90046001600160801b03169050866001600160801b03168b6001600160801b0319168d6001600160401b03165f5160206149105f395f51905f52858c8b5f015f9054906101000a90046001600160801b0316878c5f0160019054906101000a90046001600160801b03168d5f015f9054906101000a900460ff16604051613a9d9695949392919061489e565b60405180910390a4505b60019150505b9998505050505050505050565b6001600160801b031987165f908152600b602090815260408083206001600160801b0387811685529252909120541685613afd57613af8878261446e565b613b07565b613b0787826144bc565b6001600160801b03198981165f818152600b602090815260408083206001600160801b038b8116808652919093529220805490941690851617909255919250906001600160401b038b165f5160206148f05f395f51905f52613b698c89612703565b875460208801518851604051613b8f94938e936001600160801b03909116928b9261489e565b60405180910390a4505050505050505050565b6001600160801b031987165f908152600a602090815260408083206001600160801b0387811685529252909120541685613be557613be0878261446e565b613bef565b613bef87826144bc565b6001600160801b03198981165f818152600a602090815260408083206001600160801b038b8116808652919093529220805490941690851617909255919250906001600160401b038b165f5160206149105f395f51905f52613b698c896117a4565b5f5f613c5e8686866132f1565b90506001836002811115613c7457613c74614620565b148015613c9057505f8480613c8b57613c8b614634565b868809115b15612fb357610f376001826148dc565b5f613cb3836001600160801b031661329c565b613cfd5760405162461bcd60e51b815260206004820152601b60248201527a50726963696e674c69622f6469766973696f6e2d62792d7a65726f60281b6044820152606401610b07565b613267611a176001600160801b03861689613d1989600a614860565b613d23919061486e565b6001600160801b038716613d388b600a614860565b6137b0919061486e565b5f610a62611a17846001600160801b0316670de0b6b3a7640000856001600160801b03166132f1565b5f612164846001600160801b031684670de0b6b3a764000085613c51565b5f60018263ffffffff16111580613da8575082516001600160801b0316155b80610a6257505060209091015163ffffffff9182169116101590565b80356001600160801b031981168114613ddb575f5ffd5b919050565b6001600160801b0381168114613df4575f5ffd5b50565b5f5f60408385031215613e08575f5ffd5b613e1183613dc4565b91506020830135613e2181613de0565b809150509250929050565b6001600160801b0391909116815260200190565b5f5f5f60608486031215613e52575f5ffd5b613e5b84613dc4565b92506020840135613e6b81613de0565b929592945050506040919091013590565b80356001600160401b0381168114613ddb575f5ffd5b803563ffffffff81168114613ddb575f5ffd5b5f5f5f5f5f5f60c08789031215613eba575f5ffd5b613ec387613e7c565b9550613ed160208801613dc4565b94506040870135613ee181613de0565b9350613eef60608801613e92565b92506080870135613eff81613de0565b915060a0870135613f0f81613de0565b809150509295509295509295565b5f60208284031215613f2d575f5ffd5b610a6282613e7c565b5f5f5f5f60808587031215613f49575f5ffd5b613f5285613e7c565b9350613f6060208601613dc4565b9250604085013591506060850135613f7781613de0565b939692955090935050565b5f5f60408385031215613f93575f5ffd5b613f9c83613e7c565b9150613faa60208401613e92565b90509250929050565b5f5f5f5f5f60a08688031215613fc7575f5ffd5b613fd086613e7c565b9450613fde60208701613dc4565b93506040860135613fee81613de0565b9250613ffc60608701613e92565b9150608086013561400c81613de0565b809150509295509295909350565b5f5f5f6060848603121561402c575f5ffd5b61403584613dc4565b9250602084013561404581613de0565b915061405360408501613e92565b90509250925092565b803561ffff81168114613ddb575f5ffd5b5f5f5f5f5f60a08688031215614081575f5ffd5b61408a8661405c565b945061409860208701613e7c565b93506140a660408701613dc4565b925060608601356140b681613de0565b91506080860135801515811461400c575f5ffd5b5f5f604083850312156140db575f5ffd5b6140e483613dc4565b9150613faa6020840161405c565b5f60208284031215614102575f5ffd5b81356001600160a01b0381168114612167575f5ffd5b5f60208284031215614128575f5ffd5b610a6282613dc4565b5f5f5f5f5f60a08688031215614145575f5ffd5b61414e86613e7c565b945061415c60208701613dc4565b9350604086013561416c81613de0565b925060608601359150608086013561400c81613de0565b5f5f83601f840112614193575f5ffd5b5081356001600160401b038111156141a9575f5ffd5b6020830191508360208285010111156141c0575f5ffd5b9250929050565b5f5f5f5f5f5f608087890312156141dc575f5ffd5b6141e587613e7c565b95506141f360208801613dc4565b945060408701356001600160401b0381111561420d575f5ffd5b61421989828a01614183565b90955093505060608701356001600160401b03811115614237575f5ffd5b61424389828a01614183565b979a9699509497509295939492505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6142956060830186614255565b82810360208401526142a78186614255565b915050826040830152949350505050565b5f5f5f606084860312156142ca575f5ffd5b6142d384613dc4565b92506020840135915060408401356142ea81613de0565b809150509250925092565b5f5f5f60608486031215614307575f5ffd5b61431084613e7c565b925061431e60208501613dc4565b915060408401356142ea81613de0565b5f6020828403121561433e575f5ffd5b5035919050565b5f5f5f5f5f5f6080878903121561435a575f5ffd5b61436387613e7c565b955060208701356001600160401b0381111561437d575f5ffd5b61438989828a01614183565b90965094505060408701356001600160401b038111156143a7575f5ffd5b6143b389828a01614183565b979a9699509497949695606090950135949350505050565b5f5f604083850312156143dc575f5ffd5b6143e583613e7c565b9150613faa60208401613dc4565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff8181168382160190811115610a6557610a656143f3565b63ffffffff92831681529116602082015260400190565b5f6020828403121561444a575f5ffd5b815160ff81168114612167575f5ffd5b6001600160401b0391909116815260200190565b6001600160801b038281168282160390811115610a6557610a656143f3565b63ffffffff9490941684526001600160801b039283166020850152908216604084015216606082015260800190565b6001600160801b038181168382160190811115610a6557610a656143f3565b61ffff9290921682526001600160801b0316602082015260400190565b63ffffffff96909616865260208601949094526001600160801b03928316604086015290821660608501521660808301526001600160401b031660a082015260c00190565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f61457860408301868861453d565b828103602084015261326781858761453d565b600181811c9082168061459f57607f821691505b6020821081036145bd57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f63ffffffff821663ffffffff81036145de576145de6143f3565b60010192915050565b606081525f6145fa60608301878961453d565b828103602084015261460d81868861453d565b9150508260408301529695505050505050565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b601f8211156146a357805f5260205f20601f840160051c810160208510156146815750805b601f840160051c820191505b818110156146a0575f815560010161468d565b50505b505050565b6001600160401b038311156146bf576146bf614648565b6146d3836146cd835461458b565b8361465c565b5f601f841160018114614704575f85156146ed5750838201355b5f19600387901b1c1916600186901b1783556146a0565b5f83815260208120601f198716915b828110156147335786850135825560209485019460019092019101614713565b508682101561474f575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b63ffffffff8281168282160390811115610a6557610a656143f3565b6001815b60018411156147b85780850481111561479c5761479c6143f3565b60018416156147aa57908102905b60019390931c928002614781565b935093915050565b5f826147ce57506001610a65565b816147da57505f610a65565b81600181146147f057600281146147fa57614816565b6001915050610a65565b60ff84111561480b5761480b6143f3565b50506001821b610a65565b5060208310610133831016604e8410600b8410161715614839575081810a610a65565b6148455f19848461477d565b805f1904821115614858576148586143f3565b029392505050565b5f610a6260ff8416836147c0565b8082028115828204841417610a6557610a656143f3565b60ff8181168382160190811115610a6557610a656143f3565b63ffffffff96909616865260208601949094526001600160801b0392831660408601529082166060850152166080830152151560a082015260c00190565b80820180821115610a6557610a656143f356fe1f5a5e518a04d4ae04df91bdcdfc726fd04628d7968eb87c8a177f55336765ff688670c8bdbd011a5a7703624480229795dd54b1ead47cb9a66061fa8b2e0b7aa264697066735822122037736688b1e69a7f3366472d63f827c0884c18babd2501e7b3530c0cf1c1ba3864736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb0000000000000000000000005f3f8ea3b54bff7795de7754866e0eac52e0881d
-----Decoded View---------------
Arg [0] : hubRegistry_ (address): 0x12044ef361Cc3446Cb7d36541C8411EE4e6f52cb
Arg [1] : deployer (address): 0x5f3f8ea3b54BFF7795dE7754866e0Eac52e0881d
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000012044ef361cc3446cb7d36541c8411ee4e6f52cb
Arg [1] : 0000000000000000000000005f3f8ea3b54bff7795de7754866e0eac52e0881d
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.