diff --git a/contracts/Hyperdrive.sol b/contracts/Hyperdrive.sol index b1996a6ae..c489b4cdd 100644 --- a/contracts/Hyperdrive.sol +++ b/contracts/Hyperdrive.sol @@ -399,31 +399,32 @@ contract Hyperdrive is MultiToken { } /// @notice Closes a short position with a specified maturity time. - /// @param _assetId The asset ID of the short. + /// @param _openSharePrice The opening share price of the short. + /// @param _maturityTime The maturity time of the short. /// @param _bondAmount The amount of shorts to close. - function closeShort(uint256 _assetId, uint256 _bondAmount) external { + function closeShort( + uint256 _openSharePrice, + uint32 _maturityTime, + uint256 _bondAmount + ) external { if (_bondAmount == 0) { revert Errors.ZeroAmount(); } - // Ensure that the asset ID refers to a short and get the open share - // price and maturity time from the short key. - ( - AssetId.AssetIdPrefix prefix, - uint256 openSharePrice, - uint256 maturityTime - ) = AssetId.decodeAssetId(_assetId); - if (prefix != AssetId.AssetIdPrefix.Short) { - revert Errors.UnexpectedAssetId(); - } - // Burn the shorts that are being closed. - _burn(_assetId, msg.sender, _bondAmount); + uint256 assetId = AssetId.encodeAssetId( + AssetId.AssetIdPrefix.Short, + _openSharePrice, + _maturityTime + ); + _burn(assetId, msg.sender, _bondAmount); shortsOutstanding -= _bondAmount; // Calculate the pool and user deltas using the trading function. - uint256 timeRemaining = block.timestamp < maturityTime - ? (maturityTime - block.timestamp).divDown(positionDuration) // use divDown to scale to fixed point + uint256 timeRemaining = block.timestamp < uint256(_maturityTime) + ? (uint256(_maturityTime) - block.timestamp).divDown( + positionDuration + ) // use divDown to scale to fixed point : 0; ( uint256 poolShareDelta, @@ -453,7 +454,7 @@ contract Hyperdrive is MultiToken { sharePrice.mulDown(sharePayment) ); uint256 interestProceeds = sharePrice - .divDown(openSharePrice) + .divDown(_openSharePrice) .sub(FixedPointMath.ONE_18) .mulDown(_bondAmount); bool success = baseToken.transfer( diff --git a/contracts/libraries/AssetId.sol b/contracts/libraries/AssetId.sol index 02ee2229c..716cc72a6 100644 --- a/contracts/libraries/AssetId.sol +++ b/contracts/libraries/AssetId.sol @@ -51,42 +51,4 @@ library AssetId { } return id; } - - /// @dev Decodes an asset ID into an identifier, extra data, and a timestamp. - /// @param _id The asset ID. - /// TODO: Update this comment when we make the range more restrictive. - /// @return prefix A one byte prefix that specifies the asset type. - /// @return data Data associated with the asset. This is an efficient way of - /// fingerprinting data as the user can supply this data, and the - /// token balance ensures that the data is associated with the asset. - /// @return timestamp_ A timestamp associated with the asset. - function decodeAssetId( - uint256 _id - ) - internal - pure - returns (AssetIdPrefix prefix, uint256 data, uint256 timestamp_) - { - // [identifier: 8 bits][data: 216 bits][timestamp: 32 bits] - assembly { - prefix := shr(0xf8, _id) - data := and( - shr(0x20, _id), - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffff - ) - timestamp_ := and(shr(0x20, _id), 0xffffffff) - } - // In the case of shorts, extra data is the share price at which the - // short was opened. Hyperdrive assumes that the yield source accrues - // non-negative interest, so an opening share price less than the fixed - // point multiplicative identity indicates corruption. In the case of - // longs, the extra data is unused. - if ( - (prefix == AssetIdPrefix.Long && data > 0) || - (prefix == AssetIdPrefix.Short && data < FixedPointMath.ONE_18) - ) { - revert Errors.AssetIDCorruption(); - } - return (prefix, data, timestamp_); - } }