Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tidy-plants-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hashgraph/asset-tokenization-contracts": minor
---

couponFor token balance bug fixed
3 changes: 3 additions & 0 deletions packages/ats/contracts/contracts/constants/resolverKeys.sol
Original file line number Diff line number Diff line change
Expand Up @@ -720,3 +720,6 @@ bytes32 constant _METADATA_RESOLVER_KEY = 0x4c3bd2753f7bc002cfee0180298759848c0f

// keccak256("security.token.standard.deactivate.resolverKey");
bytes32 constant _DEACTIVATE_RESOLVER_KEY = 0x28edc8979475f616e9ee33c89ffa66022cb1bd6d3c555cbb4c4acaefa3974f96;

// keccak256('security.token.standard.nominalValueAtSnapshot.resolverKey');
bytes32 constant _NOMINAL_VALUE_AT_SNAPSHOT_RESOLVER_KEY = 0xa9eb978fb9b2f23119fbe6dc3a3f6010398d58b37b5221961eaa584486c8c6fb;
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { ClearingStorageWrapper } from "./ClearingStorageWrapper.sol";
import { ClearingReadOps } from "../orchestrator/ClearingReadOps.sol";
import { ERC3643StorageWrapper } from "../core/ERC3643StorageWrapper.sol";
import { TimeTravelStorageWrapper } from "../../test/testTimeTravel/timeTravel/TimeTravelStorageWrapper.sol";
import { NominalValueStorageWrapper } from "./nominalValue/NominalValueStorageWrapper.sol";

/**
* @notice Central storage layout for all snapshot-related data across the token system.
Expand Down Expand Up @@ -68,6 +69,10 @@ struct SnapshotStorage {
mapping(uint256 => SnapshotsAddress) tokenHoldersSnapshots;
/// @dev Snapshots for total number of token holders
Snapshots totalTokenHoldersSnapshots;
/// @dev Snapshots for the nominal value
Snapshots nominalValueSnapshots;
/// @dev Snapshots for the nominal value decimals
Snapshots nominalValueDecimalsSnapshots;
}

/**
Expand Down Expand Up @@ -133,6 +138,17 @@ library SnapshotsStorageWrapper {
updateSnapshot(_snapshotStorage().totalSupplySnapshots, ERC20StorageWrapper.totalSupply());
}

function updateNominalValueSnapshot() internal {
updateSnapshot(_snapshotStorage().nominalValueSnapshots, NominalValueStorageWrapper.getNominalValue());
}

function updateNominalValueDecimalsSnapshot() internal {
updateSnapshot(
_snapshotStorage().nominalValueDecimalsSnapshots,
NominalValueStorageWrapper.getNominalValueDecimals()
);
}

/**
* @dev Update balance and/or total supply snapshots before the values are modified. This is implemented
* in the _beforeTokenTransfer hook, which is executed for _mint, _burn, and _transfer operations.
Expand Down Expand Up @@ -535,6 +551,16 @@ library SnapshotsStorageWrapper {
return snapshotted ? value : ERC20StorageWrapper.totalSupply();
}

function nominalValueAtSnapshot(uint256 snapshotId) internal view returns (uint256) {
(bool snapshotted, uint256 value) = valueAt(snapshotId, _snapshotStorage().nominalValueSnapshots);
return snapshotted ? value : NominalValueStorageWrapper.getNominalValue();
}

function nominalValueDecimalsAtSnapshot(uint256 snapshotId) internal view returns (uint8) {
(bool snapshotted, uint256 value) = valueAt(snapshotId, _snapshotStorage().nominalValueDecimalsSnapshots);
return snapshotted ? uint8(value) : NominalValueStorageWrapper.getNominalValueDecimals();
}

function getCurrentSnapshotId() internal view returns (uint256) {
return _snapshotStorage().currentSnapshotId.current();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,25 @@ library CouponStorageWrapper {

if (registeredCoupon.coupon.recordDate < TimeTravelStorageWrapper.getBlockTimestamp() && !isDisabled) {
couponFor_.recordDateReached = true;
couponFor_.tokenBalance = (registeredCoupon.snapshotId != 0)
? SnapshotsStorageWrapper.getTotalBalanceOfAtSnapshot(registeredCoupon.snapshotId, account)
: ERC3643StorageWrapper.getTotalBalanceForAdjustedAt(
if (registeredCoupon.snapshotId != 0) {
couponFor_.tokenBalance = SnapshotsStorageWrapper.getTotalBalanceOfAtSnapshot(
registeredCoupon.snapshotId,
account
);
couponFor_.decimals = SnapshotsStorageWrapper.decimalsAtSnapshot(registeredCoupon.snapshotId);
couponFor_.nominalValue = SnapshotsStorageWrapper.nominalValueAtSnapshot(registeredCoupon.snapshotId);
couponFor_.nominalValueDecimals = SnapshotsStorageWrapper.nominalValueDecimalsAtSnapshot(
registeredCoupon.snapshotId
);
} else {
couponFor_.tokenBalance = ERC3643StorageWrapper.getTotalBalanceForAdjustedAt(
account,
TimeTravelStorageWrapper.getBlockTimestamp()
registeredCoupon.coupon.recordDate
);
couponFor_.decimals = ERC20StorageWrapper.decimalsAdjustedAt(TimeTravelStorageWrapper.getBlockTimestamp());
couponFor_.nominalValue = NominalValueStorageWrapper.getNominalValue();
couponFor_.decimals = ERC20StorageWrapper.decimalsAdjustedAt(registeredCoupon.coupon.recordDate);
couponFor_.nominalValue = NominalValueStorageWrapper.getNominalValue();
couponFor_.nominalValueDecimals = NominalValueStorageWrapper.getNominalValueDecimals();
}
}

couponFor_.couponAmount = _calculateCouponAmount(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pragma solidity >=0.8.0 <0.9.0;
import { BondStorageWrapper } from "../BondStorageWrapper.sol";
import { EquityStorageWrapper } from "../EquityStorageWrapper.sol";
import { _NOMINAL_VALUE_STORAGE_POSITION } from "../../../constants/storagePositions.sol";
import { SnapshotsStorageWrapper } from "../SnapshotsStorageWrapper.sol";
import { ScheduledTasksStorageWrapper } from "../ScheduledTasksStorageWrapper.sol";

/**
* @title NominalValueStorageWrapper - Nominal Value Storage Wrapper
Expand Down Expand Up @@ -52,6 +54,11 @@ library NominalValueStorageWrapper {
migrateBondNominalValue();
migrateEquityNominalValue();

ScheduledTasksStorageWrapper.callTriggerPendingScheduledCrossOrderedTasks();

SnapshotsStorageWrapper.updateNominalValueSnapshot();
SnapshotsStorageWrapper.updateNominalValueDecimalsSnapshot();

NominalValueDataStorage storage nvData_ = _nominalValueStorage();
nvData_.nominalValue = _nominalValue;
nvData_.nominalValueDecimals = _nominalValueDecimals;
Expand Down
2 changes: 2 additions & 0 deletions packages/ats/contracts/contracts/facets/IAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import { IKyc } from "./layer_1/kyc/IKyc.sol";
// directly when testing KPI-linked or SPTR interest rate facets.
import { ILoan } from "./layer_2/loan/ILoan.sol";
import { INominalValue } from "./layer_2/nominalValue/INominalValue.sol";
import { INominalValueAtSnapshot } from "./nominalValueAtSnapshot/INominalValueAtSnapshot.sol";
import { IPause } from "./pause/IPause.sol";
import { ILoansPortfolio } from "./layer_2/loansPortfolio/ILoansPortfolio.sol";
import { IVoting } from "./layer_2/voting/IVoting.sol";
Expand Down Expand Up @@ -192,6 +193,7 @@ interface IAsset is
IProtectedPartitions,
IProceedRecipients,
INominalValue,
INominalValueAtSnapshot,
IAmortization,
ILoan,
IAdjustBalances,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ interface ICouponTypes is IKpiLinkedRateErrors {
*/
struct CouponFor {
uint256 tokenBalance;
uint256 nominalValue;
uint8 decimals;
uint256 nominalValue;
uint256 nominalValueDecimals;
bool recordDateReached;
Coupon coupon;
CouponAmountFor couponAmount;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0 <0.9.0;

/**
* @title INominalValueAtSnapshot
*/
interface INominalValueAtSnapshot {
function nominalValueAtSnapshot(uint256 _snapshotID) external view returns (uint256 nominalValue_);

function nominalValueDecimalsAtSnapshot(uint256 _snapshotID) external view returns (uint8 nominalValueDecimals_);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NatSpec, please

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0 <0.9.0;

import { INominalValueAtSnapshot } from "./INominalValueAtSnapshot.sol";
import { SnapshotsStorageWrapper } from "../../domain/asset/SnapshotsStorageWrapper.sol";

/**
* @title NominalValueAtSnapshot
*/
abstract contract NominalValueAtSnapshot is INominalValueAtSnapshot {
/// @inheritdoc INominalValueAtSnapshot
function nominalValueAtSnapshot(uint256 _snapshotID) external view override returns (uint256 nominalValue_) {
nominalValue_ = SnapshotsStorageWrapper.nominalValueAtSnapshot(_snapshotID);
}

function nominalValueDecimalsAtSnapshot(
uint256 _snapshotID
) external view override returns (uint8 nominalValueDecimals_) {
nominalValueDecimals_ = SnapshotsStorageWrapper.nominalValueDecimalsAtSnapshot(_snapshotID);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

natspec please

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0 <0.9.0;

import { INominalValueAtSnapshot } from "./INominalValueAtSnapshot.sol";
import { NominalValueAtSnapshot } from "./NominalValueAtSnapshot.sol";
import { IStaticFunctionSelectors } from "../../infrastructure/proxy/IStaticFunctionSelectors.sol";
import { _NOMINAL_VALUE_AT_SNAPSHOT_RESOLVER_KEY } from "../../constants/resolverKeys.sol";

/**
* @title NominalValueAtSnapshotFacet
*/
contract NominalValueAtSnapshotFacet is NominalValueAtSnapshot, IStaticFunctionSelectors {
/// @inheritdoc IStaticFunctionSelectors
function getStaticResolverKey() external pure override returns (bytes32 staticResolverKey_) {
staticResolverKey_ = _NOMINAL_VALUE_AT_SNAPSHOT_RESOLVER_KEY;
}

/// @inheritdoc IStaticFunctionSelectors
function getStaticFunctionSelectors() external pure override returns (bytes4[] memory staticFunctionSelectors_) {
uint256 selectorIndex = 2;
staticFunctionSelectors_ = new bytes4[](selectorIndex);
unchecked {
staticFunctionSelectors_[--selectorIndex] = this.nominalValueAtSnapshot.selector;
staticFunctionSelectors_[--selectorIndex] = this.nominalValueDecimalsAtSnapshot.selector;
}
}

/// @inheritdoc IStaticFunctionSelectors
function getStaticInterfaceIds() external pure override returns (bytes4[] memory staticInterfaceIds_) {
uint256 selectorIndex = 1;
staticInterfaceIds_ = new bytes4[](selectorIndex);
unchecked {
staticInterfaceIds_[--selectorIndex] = type(INominalValueAtSnapshot).interfaceId;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just build the two arrays as normal, without index.

}
Loading
Loading