Diff
checker
Text
Text
Bilder
Dokumente
Excel
Ordner
Legal
Enterprise
Desktop-App
Preise
Einloggen
Diffchecker Desktop herunterladen
Texte vergleichen
Finde den Unterschied zwischen zwei Textdateien
Werkzeuge
Verlauf
Live-Editor
Leerzeichen ausblenden
Gleiches ausblenden
Zeilenumbruch aus
Ansicht
Zweispaltig
Einspaltig
Vergleichsgenauigkeit
Intelligent
Wort
Zeichen
Textstile
Darstellung ändern
Syntaxhervorhebung
Syntax auswählen
Ignorieren
Text umwandeln
Zur ersten Änderung
Eingabe bearbeiten
Diffchecker Desktop
Der sicherste Weg, Diffchecker zu nutzen. Hol dir die Desktop-App: Deine Diffs verlassen nie deinen Computer!
Desktop holen
Position <> PositionV2
Erstellt
vor 4 Jahren
Diff läuft nie ab
Löschen
Exportieren
Teilen
Erklären
13 Entfernungen
Zeilen
Gesamt
Entfernt
Zeichen
Gesamt
Entfernt
Um diese Funktion weiterhin zu nutzen, aktualisiere auf
Diff
checker
Pro
Preise anzeigen
260 Zeilen
Kopieren
19 Hinzufügungen
Zeilen
Gesamt
Hinzugefügt
Zeichen
Gesamt
Hinzugefügt
Um diese Funktion weiterhin zu nutzen, aktualisiere auf
Diff
checker
Pro
Preise anzeigen
263 Zeilen
Kopieren
/*
/*
Kopieren
Kopiert
Kopieren
Kopiert
Copyright 202
0
Set Labs Inc.
Copyright 202
2
Set Labs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.
SPDX-License-Identifier: Apache License, Version 2.0
SPDX-License-Identifier: Apache License, Version 2.0
*/
*/
pragma solidity 0.6.10;
pragma solidity 0.6.10;
pragma experimental "ABIEncoderV2";
pragma experimental "ABIEncoderV2";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeCast } from "@openzeppelin/contracts/utils/SafeCast.sol";
import { SafeCast } from "@openzeppelin/contracts/utils/SafeCast.sol";
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { SignedSafeMath } from "@openzeppelin/contracts/math/SignedSafeMath.sol";
import { SignedSafeMath } from "@openzeppelin/contracts/math/SignedSafeMath.sol";
import { ISetToken } from "../../interfaces/ISetToken.sol";
import { ISetToken } from "../../interfaces/ISetToken.sol";
import { PreciseUnitMath } from "../../lib/PreciseUnitMath.sol";
import { PreciseUnitMath } from "../../lib/PreciseUnitMath.sol";
/**
/**
Kopieren
Kopiert
Kopieren
Kopiert
* @title Position
* @title Position
V2
* @author Set Protocol
* @author Set Protocol
*
*
Kopieren
Kopiert
Kopieren
Kopiert
* Collection of helper functions for handling and updating SetToken Positions
* Collection of helper functions for handling and updating SetToken Positions
.
*
*
* CHANGELOG:
* CHANGELOG:
Kopieren
Kopiert
Kopieren
Kopiert
* - Updated editExternalPosition to work when no external position is associated with module
* - `Position` library has all internal functions which are inlined to the module contract during compilation.
* Inlining functions increases bytecode size of the module contract. This library contains the same functions
* as `Position` library but all the functions have public/external access modifier. Thus, making this version
* linkable which helps in reducing bytecode size of the module contract.
*/
*/
Kopieren
Kopiert
Kopieren
Kopiert
library Position
{
library Position
V2
{
using SafeCast for uint256;
using SafeCast for uint256;
using SafeMath for uint256;
using SafeMath for uint256;
using SafeCast for int256;
using SafeCast for int256;
using SignedSafeMath for int256;
using SignedSafeMath for int256;
using PreciseUnitMath for uint256;
using PreciseUnitMath for uint256;
/* ============ Helper ============ */
/* ============ Helper ============ */
/**
/**
* Returns whether the SetToken has a default position for a given component (if the real unit is > 0)
* Returns whether the SetToken has a default position for a given component (if the real unit is > 0)
*/
*/
Kopieren
Kopiert
Kopieren
Kopiert
function hasDefaultPosition(ISetToken _setToken, address _component)
internal
view returns(bool) {
function hasDefaultPosition(ISetToken _setToken, address _component)
public
view returns(bool) {
return _setToken.getDefaultPositionRealUnit(_component) > 0;
return _setToken.getDefaultPositionRealUnit(_component) > 0;
}
}
/**
/**
* Returns whether the SetToken has an external position for a given component (if # of position modules is > 0)
* Returns whether the SetToken has an external position for a given component (if # of position modules is > 0)
*/
*/
Kopieren
Kopiert
Kopieren
Kopiert
function hasExternalPosition(ISetToken _setToken, address _component)
internal
view returns(bool) {
function hasExternalPosition(ISetToken _setToken, address _component)
public
view returns(bool) {
return _setToken.getExternalPositionModules(_component).length > 0;
return _setToken.getExternalPositionModules(_component).length > 0;
}
}
/**
/**
* Returns whether the SetToken component default position real unit is greater than or equal to units passed in.
* Returns whether the SetToken component default position real unit is greater than or equal to units passed in.
*/
*/
Kopieren
Kopiert
Kopieren
Kopiert
function hasSufficientDefaultUnits(ISetToken _setToken, address _component, uint256 _unit)
in
ternal view returns(bool) {
function hasSufficientDefaultUnits(ISetToken _setToken, address _component, uint256 _unit)
ex
ternal view returns(bool) {
return _setToken.getDefaultPositionRealUnit(_component) >= _unit.toInt256();
return _setToken.getDefaultPositionRealUnit(_component) >= _unit.toInt256();
}
}
/**
/**
* Returns whether the SetToken component external position is greater than or equal to the real units passed in.
* Returns whether the SetToken component external position is greater than or equal to the real units passed in.
*/
*/
function hasSufficientExternalUnits(
function hasSufficientExternalUnits(
ISetToken _setToken,
ISetToken _setToken,
address _component,
address _component,
address _positionModule,
address _positionModule,
uint256 _unit
uint256 _unit
)
)
Kopieren
Kopiert
Kopieren
Kopiert
in
ternal
ex
ternal
view
view
returns(bool)
returns(bool)
{
{
return _setToken.getExternalPositionRealUnit(_component, _positionModule) >= _unit.toInt256();
return _setToken.getExternalPositionRealUnit(_component, _positionModule) >= _unit.toInt256();
}
}
/**
/**
* If the position does not exist, create a new Position and add to the SetToken. If it already exists,
* If the position does not exist, create a new Position and add to the SetToken. If it already exists,
* then set the position units. If the new units is 0, remove the position. Handles adding/removing of
* then set the position units. If the new units is 0, remove the position. Handles adding/removing of
* components where needed (in light of potential external positions).
* components where needed (in light of potential external positions).
*
*
* @param _setToken Address of SetToken being modified
* @param _setToken Address of SetToken being modified
* @param _component Address of the component
* @param _component Address of the component
* @param _newUnit Quantity of Position units - must be >= 0
* @param _newUnit Quantity of Position units - must be >= 0
*/
*/
Kopieren
Kopiert
Kopieren
Kopiert
function editDefaultPosition(ISetToken _setToken, address _component, uint256 _newUnit)
internal
{
function editDefaultPosition(ISetToken _setToken, address _component, uint256 _newUnit)
public
{
bool isPositionFound = hasDefaultPosition(_setToken, _component);
bool isPositionFound = hasDefaultPosition(_setToken, _component);
if (!isPositionFound && _newUnit > 0) {
if (!isPositionFound && _newUnit > 0) {
// If there is no Default Position and no External Modules, then component does not exist
// If there is no Default Position and no External Modules, then component does not exist
if (!hasExternalPosition(_setToken, _component)) {
if (!hasExternalPosition(_setToken, _component)) {
_setToken.addComponent(_component);
_setToken.addComponent(_component);
}
}
} else if (isPositionFound && _newUnit == 0) {
} else if (isPositionFound && _newUnit == 0) {
// If there is a Default Position and no external positions, remove the component
// If there is a Default Position and no external positions, remove the component
if (!hasExternalPosition(_setToken, _component)) {
if (!hasExternalPosition(_setToken, _component)) {
_setToken.removeComponent(_component);
_setToken.removeComponent(_component);
}
}
}
}
_setToken.editDefaultPositionUnit(_component, _newUnit.toInt256());
_setToken.editDefaultPositionUnit(_component, _newUnit.toInt256());
}
}
/**
/**
* Update an external position and remove and external positions or components if necessary. The logic flows as follows:
* Update an external position and remove and external positions or components if necessary. The logic flows as follows:
* 1) If component is not already added then add component and external position.
* 1) If component is not already added then add component and external position.
* 2) If component is added but no existing external position using the passed module exists then add the external position.
* 2) If component is added but no existing external position using the passed module exists then add the external position.
* 3) If the existing position is being added to then just update the unit and data
* 3) If the existing position is being added to then just update the unit and data
* 4) If the position is being closed and no other external positions or default positions are associated with the component
* 4) If the position is being closed and no other external positions or default positions are associated with the component
* then untrack the component and remove external position.
* then untrack the component and remove external position.
* 5) If the position is being closed and other existing positions still exist for the component then just remove the
* 5) If the position is being closed and other existing positions still exist for the component then just remove the
* external position.
* external position.
*
*
* @param _setToken SetToken being updated
* @param _setToken SetToken being updated
* @param _component Component position being updated
* @param _component Component position being updated
* @param _module Module external position is associated with
* @param _module Module external position is associated with
* @param _newUnit Position units of new external position
* @param _newUnit Position units of new external position
* @param _data Arbitrary data associated with the position
* @param _data Arbitrary data associated with the position
*/
*/
function editExternalPosition(
function editExternalPosition(
ISetToken _setToken,
ISetToken _setToken,
address _component,
address _component,
address _module,
address _module,
int256 _newUnit,
int256 _newUnit,
bytes memory _data
bytes memory _data
)
)
Kopieren
Kopiert
Kopieren
Kopiert
in
ternal
ex
ternal
{
{
if (_newUnit != 0) {
if (_newUnit != 0) {
if (!_setToken.isComponent(_component)) {
if (!_setToken.isComponent(_component)) {
_setToken.addComponent(_component);
_setToken.addComponent(_component);
_setToken.addExternalPositionModule(_component, _module);
_setToken.addExternalPositionModule(_component, _module);
} else if (!_setToken.isExternalPositionModule(_component, _module)) {
} else if (!_setToken.isExternalPositionModule(_component, _module)) {
_setToken.addExternalPositionModule(_component, _module);
_setToken.addExternalPositionModule(_component, _module);
}
}
_setToken.editExternalPositionUnit(_component, _module, _newUnit);
_setToken.editExternalPositionUnit(_component, _module, _newUnit);
_setToken.editExternalPositionData(_component, _module, _data);
_setToken.editExternalPositionData(_component, _module, _data);
} else {
} else {
require(_data.length == 0, "Passed data must be null");
require(_data.length == 0, "Passed data must be null");
// If no default or external position remaining then remove component from components array
// If no default or external position remaining then remove component from components array
if (_setToken.getExternalPositionRealUnit(_component, _module) != 0) {
if (_setToken.getExternalPositionRealUnit(_component, _module) != 0) {
address[] memory positionModules = _setToken.getExternalPositionModules(_component);
address[] memory positionModules = _setToken.getExternalPositionModules(_component);
if (_setToken.getDefaultPositionRealUnit(_component) == 0 && positionModules.length == 1) {
if (_setToken.getDefaultPositionRealUnit(_component) == 0 && positionModules.length == 1) {
require(positionModules[0] == _module, "External positions must be 0 to remove component");
require(positionModules[0] == _module, "External positions must be 0 to remove component");
_setToken.removeComponent(_component);
_setToken.removeComponent(_component);
}
}
_setToken.removeExternalPositionModule(_component, _module);
_setToken.removeExternalPositionModule(_component, _module);
}
}
}
}
}
}
/**
/**
* Get total notional amount of Default position
* Get total notional amount of Default position
*
*
* @param _setTokenSupply Supply of SetToken in precise units (10^18)
* @param _setTokenSupply Supply of SetToken in precise units (10^18)
* @param _positionUnit Quantity of Position units
* @param _positionUnit Quantity of Position units
*
*
* @return Total notional amount of units
* @return Total notional amount of units
*/
*/
Kopieren
Kopiert
Kopieren
Kopiert
function getDefaultTotalNotional(uint256 _setTokenSupply, uint256 _positionUnit)
in
ternal pure returns (uint256) {
function getDefaultTotalNotional(uint256 _setTokenSupply, uint256 _positionUnit)
ex
ternal pure returns (uint256) {
return _setTokenSupply.preciseMul(_positionUnit);
return _setTokenSupply.preciseMul(_positionUnit);
}
}
/**
/**
* Get position unit from total notional amount
* Get position unit from total notional amount
*
*
* @param _setTokenSupply Supply of SetToken in precise units (10^18)
* @param _setTokenSupply Supply of SetToken in precise units (10^18)
* @param _totalNotional Total notional amount of component prior to
* @param _totalNotional Total notional amount of component prior to
* @return Default position unit
* @return Default position unit
*/
*/
Kopieren
Kopiert
Kopieren
Kopiert
function getDefaultPositionUnit(uint256 _setTokenSupply, uint256 _totalNotional)
in
ternal pure returns (uint256) {
function getDefaultPositionUnit(uint256 _setTokenSupply, uint256 _totalNotional)
ex
ternal pure returns (uint256) {
return _totalNotional.preciseDiv(_setTokenSupply);
return _totalNotional.preciseDiv(_setTokenSupply);
}
}
/**
/**
* Get the total tracked balance - total supply * position unit
* Get the total tracked balance - total supply * position unit
*
*
* @param _setToken Address of the SetToken
* @param _setToken Address of the SetToken
* @param _component Address of the component
* @param _component Address of the component
* @return Notional tracked balance
* @return Notional tracked balance
*/
*/
Kopieren
Kopiert
Kopieren
Kopiert
function getDefaultTrackedBalance(ISetToken _setToken, address _component)
in
ternal view returns(uint256) {
function getDefaultTrackedBalance(ISetToken _setToken, address _component)
ex
ternal view returns(uint256) {
int256 positionUnit = _setToken.getDefaultPositionRealUnit(_component);
int256 positionUnit = _setToken.getDefaultPositionRealUnit(_component);
return _setToken.totalSupply().preciseMul(positionUnit.toUint256());
return _setToken.totalSupply().preciseMul(positionUnit.toUint256());
}
}
/**
/**
* Calculates the new default position unit and performs the edit with the new unit
* Calculates the new default position unit and performs the edit with the new unit
*
*
* @param _setToken Address of the SetToken
* @param _setToken Address of the SetToken
* @param _component Address of the component
* @param _component Address of the component
* @param _setTotalSupply Current SetToken supply
* @param _setTotalSupply Current SetToken supply
* @param _componentPreviousBalance Pre-action component balance
* @param _componentPreviousBalance Pre-action component balance
* @return Current component balance
* @return Current component balance
* @return Previous position unit
* @return Previous position unit
* @return New position unit
* @return New position unit
*/
*/
function calculateAndEditDefaultPosition(
function calculateAndEditDefaultPosition(
ISetToken _setToken,
ISetToken _setToken,
address _component,
address _component,
uint256 _setTotalSupply,
uint256 _setTotalSupply,
uint256 _componentPreviousBalance
uint256 _componentPreviousBalance
)
)
Kopieren
Kopiert
Kopieren
Kopiert
in
ternal
ex
ternal
returns(uint256, uint256, uint256)
returns(uint256, uint256, uint256)
{
{
uint256 currentBalance = IERC20(_component).balanceOf(address(_setToken));
uint256 currentBalance = IERC20(_component).balanceOf(address(_setToken));
uint256 positionUnit = _setToken.getDefaultPositionRealUnit(_component).toUint256();
uint256 positionUnit = _setToken.getDefaultPositionRealUnit(_component).toUint256();
uint256 newTokenUnit;
uint256 newTokenUnit;
if (currentBalance > 0) {
if (currentBalance > 0) {
newTokenUnit = calculateDefaultEditPositionUnit(
newTokenUnit = calculateDefaultEditPositionUnit(
_setTotalSupply,
_setTotalSupply,
_componentPreviousBalance,
_componentPreviousBalance,
currentBalance,
currentBalance,
positionUnit
positionUnit
);
);
} else {
} else {
newTokenUnit = 0;
newTokenUnit = 0;
}
}
editDefaultPosition(_setToken, _component, newTokenUnit);
editDefaultPosition(_setToken, _component, newTokenUnit);
return (currentBalance, positionUnit, newTokenUnit);
return (currentBalance, positionUnit, newTokenUnit);
}
}
/**
/**
* Calculate the new position unit given total notional values pre and post executing an action that changes SetToken state
* Calculate the new position unit given total notional values pre and post executing an action that changes SetToken state
* The intention is to make updates to the units without accidentally picking up airdropped assets as well.
* The intention is to make updates to the units without accidentally picking up airdropped assets as well.
*
*
* @param _setTokenSupply Supply of SetToken in precise units (10^18)
* @param _setTokenSupply Supply of SetToken in precise units (10^18)
* @param _preTotalNotional Total notional amount of component prior to executing action
* @param _preTotalNotional Total notional amount of component prior to executing action
* @param _postTotalNotional Total notional amount of component after the executing action
* @param _postTotalNotional Total notional amount of component after the executing action
* @param _prePositionUnit Position unit of SetToken prior to executing action
* @param _prePositionUnit Position unit of SetToken prior to executing action
* @return New position unit
* @return New position unit
*/
*/
function calculateDefaultEditPositionUnit(
function calculateDefaultEditPositionUnit(
uint256 _setTokenSupply,
uint256 _setTokenSupply,
uint256 _preTotalNotional,
uint256 _preTotalNotional,
uint256 _postTotalNotional,
uint256 _postTotalNotional,
uint256 _prePositionUnit
uint256 _prePositionUnit
)
)
Kopieren
Kopiert
Kopieren
Kopiert
internal
public
pure
pure
returns (uint256)
returns (uint256)
{
{
// If pre action total notional amount is greater then subtract post action total notional and calculate new position units
// If pre action total notional amount is greater then subtract post action total notional and calculate new position units
uint256 airdroppedAmount = _preTotalNotional.sub(_prePositionUnit.preciseMul(_setTokenSupply));
uint256 airdroppedAmount = _preTotalNotional.sub(_prePositionUnit.preciseMul(_setTokenSupply));
return _postTotalNotional.sub(airdroppedAmount).preciseDiv(_setTokenSupply);
return _postTotalNotional.sub(airdroppedAmount).preciseDiv(_setTokenSupply);
}
}
}
}
Gespeicherte Diffs
Originaltext
Datei öffnen
/* Copyright 2020 Set Labs Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. SPDX-License-Identifier: Apache License, Version 2.0 */ pragma solidity 0.6.10; pragma experimental "ABIEncoderV2"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/SafeCast.sol"; import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { SignedSafeMath } from "@openzeppelin/contracts/math/SignedSafeMath.sol"; import { ISetToken } from "../../interfaces/ISetToken.sol"; import { PreciseUnitMath } from "../../lib/PreciseUnitMath.sol"; /** * @title Position * @author Set Protocol * * Collection of helper functions for handling and updating SetToken Positions * * CHANGELOG: * - Updated editExternalPosition to work when no external position is associated with module */ library Position { using SafeCast for uint256; using SafeMath for uint256; using SafeCast for int256; using SignedSafeMath for int256; using PreciseUnitMath for uint256; /* ============ Helper ============ */ /** * Returns whether the SetToken has a default position for a given component (if the real unit is > 0) */ function hasDefaultPosition(ISetToken _setToken, address _component) internal view returns(bool) { return _setToken.getDefaultPositionRealUnit(_component) > 0; } /** * Returns whether the SetToken has an external position for a given component (if # of position modules is > 0) */ function hasExternalPosition(ISetToken _setToken, address _component) internal view returns(bool) { return _setToken.getExternalPositionModules(_component).length > 0; } /** * Returns whether the SetToken component default position real unit is greater than or equal to units passed in. */ function hasSufficientDefaultUnits(ISetToken _setToken, address _component, uint256 _unit) internal view returns(bool) { return _setToken.getDefaultPositionRealUnit(_component) >= _unit.toInt256(); } /** * Returns whether the SetToken component external position is greater than or equal to the real units passed in. */ function hasSufficientExternalUnits( ISetToken _setToken, address _component, address _positionModule, uint256 _unit ) internal view returns(bool) { return _setToken.getExternalPositionRealUnit(_component, _positionModule) >= _unit.toInt256(); } /** * If the position does not exist, create a new Position and add to the SetToken. If it already exists, * then set the position units. If the new units is 0, remove the position. Handles adding/removing of * components where needed (in light of potential external positions). * * @param _setToken Address of SetToken being modified * @param _component Address of the component * @param _newUnit Quantity of Position units - must be >= 0 */ function editDefaultPosition(ISetToken _setToken, address _component, uint256 _newUnit) internal { bool isPositionFound = hasDefaultPosition(_setToken, _component); if (!isPositionFound && _newUnit > 0) { // If there is no Default Position and no External Modules, then component does not exist if (!hasExternalPosition(_setToken, _component)) { _setToken.addComponent(_component); } } else if (isPositionFound && _newUnit == 0) { // If there is a Default Position and no external positions, remove the component if (!hasExternalPosition(_setToken, _component)) { _setToken.removeComponent(_component); } } _setToken.editDefaultPositionUnit(_component, _newUnit.toInt256()); } /** * Update an external position and remove and external positions or components if necessary. The logic flows as follows: * 1) If component is not already added then add component and external position. * 2) If component is added but no existing external position using the passed module exists then add the external position. * 3) If the existing position is being added to then just update the unit and data * 4) If the position is being closed and no other external positions or default positions are associated with the component * then untrack the component and remove external position. * 5) If the position is being closed and other existing positions still exist for the component then just remove the * external position. * * @param _setToken SetToken being updated * @param _component Component position being updated * @param _module Module external position is associated with * @param _newUnit Position units of new external position * @param _data Arbitrary data associated with the position */ function editExternalPosition( ISetToken _setToken, address _component, address _module, int256 _newUnit, bytes memory _data ) internal { if (_newUnit != 0) { if (!_setToken.isComponent(_component)) { _setToken.addComponent(_component); _setToken.addExternalPositionModule(_component, _module); } else if (!_setToken.isExternalPositionModule(_component, _module)) { _setToken.addExternalPositionModule(_component, _module); } _setToken.editExternalPositionUnit(_component, _module, _newUnit); _setToken.editExternalPositionData(_component, _module, _data); } else { require(_data.length == 0, "Passed data must be null"); // If no default or external position remaining then remove component from components array if (_setToken.getExternalPositionRealUnit(_component, _module) != 0) { address[] memory positionModules = _setToken.getExternalPositionModules(_component); if (_setToken.getDefaultPositionRealUnit(_component) == 0 && positionModules.length == 1) { require(positionModules[0] == _module, "External positions must be 0 to remove component"); _setToken.removeComponent(_component); } _setToken.removeExternalPositionModule(_component, _module); } } } /** * Get total notional amount of Default position * * @param _setTokenSupply Supply of SetToken in precise units (10^18) * @param _positionUnit Quantity of Position units * * @return Total notional amount of units */ function getDefaultTotalNotional(uint256 _setTokenSupply, uint256 _positionUnit) internal pure returns (uint256) { return _setTokenSupply.preciseMul(_positionUnit); } /** * Get position unit from total notional amount * * @param _setTokenSupply Supply of SetToken in precise units (10^18) * @param _totalNotional Total notional amount of component prior to * @return Default position unit */ function getDefaultPositionUnit(uint256 _setTokenSupply, uint256 _totalNotional) internal pure returns (uint256) { return _totalNotional.preciseDiv(_setTokenSupply); } /** * Get the total tracked balance - total supply * position unit * * @param _setToken Address of the SetToken * @param _component Address of the component * @return Notional tracked balance */ function getDefaultTrackedBalance(ISetToken _setToken, address _component) internal view returns(uint256) { int256 positionUnit = _setToken.getDefaultPositionRealUnit(_component); return _setToken.totalSupply().preciseMul(positionUnit.toUint256()); } /** * Calculates the new default position unit and performs the edit with the new unit * * @param _setToken Address of the SetToken * @param _component Address of the component * @param _setTotalSupply Current SetToken supply * @param _componentPreviousBalance Pre-action component balance * @return Current component balance * @return Previous position unit * @return New position unit */ function calculateAndEditDefaultPosition( ISetToken _setToken, address _component, uint256 _setTotalSupply, uint256 _componentPreviousBalance ) internal returns(uint256, uint256, uint256) { uint256 currentBalance = IERC20(_component).balanceOf(address(_setToken)); uint256 positionUnit = _setToken.getDefaultPositionRealUnit(_component).toUint256(); uint256 newTokenUnit; if (currentBalance > 0) { newTokenUnit = calculateDefaultEditPositionUnit( _setTotalSupply, _componentPreviousBalance, currentBalance, positionUnit ); } else { newTokenUnit = 0; } editDefaultPosition(_setToken, _component, newTokenUnit); return (currentBalance, positionUnit, newTokenUnit); } /** * Calculate the new position unit given total notional values pre and post executing an action that changes SetToken state * The intention is to make updates to the units without accidentally picking up airdropped assets as well. * * @param _setTokenSupply Supply of SetToken in precise units (10^18) * @param _preTotalNotional Total notional amount of component prior to executing action * @param _postTotalNotional Total notional amount of component after the executing action * @param _prePositionUnit Position unit of SetToken prior to executing action * @return New position unit */ function calculateDefaultEditPositionUnit( uint256 _setTokenSupply, uint256 _preTotalNotional, uint256 _postTotalNotional, uint256 _prePositionUnit ) internal pure returns (uint256) { // If pre action total notional amount is greater then subtract post action total notional and calculate new position units uint256 airdroppedAmount = _preTotalNotional.sub(_prePositionUnit.preciseMul(_setTokenSupply)); return _postTotalNotional.sub(airdroppedAmount).preciseDiv(_setTokenSupply); } }
Bearbeitung
Datei öffnen
/* Copyright 2022 Set Labs Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. SPDX-License-Identifier: Apache License, Version 2.0 */ pragma solidity 0.6.10; pragma experimental "ABIEncoderV2"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/SafeCast.sol"; import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { SignedSafeMath } from "@openzeppelin/contracts/math/SignedSafeMath.sol"; import { ISetToken } from "../../interfaces/ISetToken.sol"; import { PreciseUnitMath } from "../../lib/PreciseUnitMath.sol"; /** * @title PositionV2 * @author Set Protocol * * Collection of helper functions for handling and updating SetToken Positions. * * CHANGELOG: * - `Position` library has all internal functions which are inlined to the module contract during compilation. * Inlining functions increases bytecode size of the module contract. This library contains the same functions * as `Position` library but all the functions have public/external access modifier. Thus, making this version * linkable which helps in reducing bytecode size of the module contract. */ library PositionV2 { using SafeCast for uint256; using SafeMath for uint256; using SafeCast for int256; using SignedSafeMath for int256; using PreciseUnitMath for uint256; /* ============ Helper ============ */ /** * Returns whether the SetToken has a default position for a given component (if the real unit is > 0) */ function hasDefaultPosition(ISetToken _setToken, address _component) public view returns(bool) { return _setToken.getDefaultPositionRealUnit(_component) > 0; } /** * Returns whether the SetToken has an external position for a given component (if # of position modules is > 0) */ function hasExternalPosition(ISetToken _setToken, address _component) public view returns(bool) { return _setToken.getExternalPositionModules(_component).length > 0; } /** * Returns whether the SetToken component default position real unit is greater than or equal to units passed in. */ function hasSufficientDefaultUnits(ISetToken _setToken, address _component, uint256 _unit) external view returns(bool) { return _setToken.getDefaultPositionRealUnit(_component) >= _unit.toInt256(); } /** * Returns whether the SetToken component external position is greater than or equal to the real units passed in. */ function hasSufficientExternalUnits( ISetToken _setToken, address _component, address _positionModule, uint256 _unit ) external view returns(bool) { return _setToken.getExternalPositionRealUnit(_component, _positionModule) >= _unit.toInt256(); } /** * If the position does not exist, create a new Position and add to the SetToken. If it already exists, * then set the position units. If the new units is 0, remove the position. Handles adding/removing of * components where needed (in light of potential external positions). * * @param _setToken Address of SetToken being modified * @param _component Address of the component * @param _newUnit Quantity of Position units - must be >= 0 */ function editDefaultPosition(ISetToken _setToken, address _component, uint256 _newUnit) public { bool isPositionFound = hasDefaultPosition(_setToken, _component); if (!isPositionFound && _newUnit > 0) { // If there is no Default Position and no External Modules, then component does not exist if (!hasExternalPosition(_setToken, _component)) { _setToken.addComponent(_component); } } else if (isPositionFound && _newUnit == 0) { // If there is a Default Position and no external positions, remove the component if (!hasExternalPosition(_setToken, _component)) { _setToken.removeComponent(_component); } } _setToken.editDefaultPositionUnit(_component, _newUnit.toInt256()); } /** * Update an external position and remove and external positions or components if necessary. The logic flows as follows: * 1) If component is not already added then add component and external position. * 2) If component is added but no existing external position using the passed module exists then add the external position. * 3) If the existing position is being added to then just update the unit and data * 4) If the position is being closed and no other external positions or default positions are associated with the component * then untrack the component and remove external position. * 5) If the position is being closed and other existing positions still exist for the component then just remove the * external position. * * @param _setToken SetToken being updated * @param _component Component position being updated * @param _module Module external position is associated with * @param _newUnit Position units of new external position * @param _data Arbitrary data associated with the position */ function editExternalPosition( ISetToken _setToken, address _component, address _module, int256 _newUnit, bytes memory _data ) external { if (_newUnit != 0) { if (!_setToken.isComponent(_component)) { _setToken.addComponent(_component); _setToken.addExternalPositionModule(_component, _module); } else if (!_setToken.isExternalPositionModule(_component, _module)) { _setToken.addExternalPositionModule(_component, _module); } _setToken.editExternalPositionUnit(_component, _module, _newUnit); _setToken.editExternalPositionData(_component, _module, _data); } else { require(_data.length == 0, "Passed data must be null"); // If no default or external position remaining then remove component from components array if (_setToken.getExternalPositionRealUnit(_component, _module) != 0) { address[] memory positionModules = _setToken.getExternalPositionModules(_component); if (_setToken.getDefaultPositionRealUnit(_component) == 0 && positionModules.length == 1) { require(positionModules[0] == _module, "External positions must be 0 to remove component"); _setToken.removeComponent(_component); } _setToken.removeExternalPositionModule(_component, _module); } } } /** * Get total notional amount of Default position * * @param _setTokenSupply Supply of SetToken in precise units (10^18) * @param _positionUnit Quantity of Position units * * @return Total notional amount of units */ function getDefaultTotalNotional(uint256 _setTokenSupply, uint256 _positionUnit) external pure returns (uint256) { return _setTokenSupply.preciseMul(_positionUnit); } /** * Get position unit from total notional amount * * @param _setTokenSupply Supply of SetToken in precise units (10^18) * @param _totalNotional Total notional amount of component prior to * @return Default position unit */ function getDefaultPositionUnit(uint256 _setTokenSupply, uint256 _totalNotional) external pure returns (uint256) { return _totalNotional.preciseDiv(_setTokenSupply); } /** * Get the total tracked balance - total supply * position unit * * @param _setToken Address of the SetToken * @param _component Address of the component * @return Notional tracked balance */ function getDefaultTrackedBalance(ISetToken _setToken, address _component) external view returns(uint256) { int256 positionUnit = _setToken.getDefaultPositionRealUnit(_component); return _setToken.totalSupply().preciseMul(positionUnit.toUint256()); } /** * Calculates the new default position unit and performs the edit with the new unit * * @param _setToken Address of the SetToken * @param _component Address of the component * @param _setTotalSupply Current SetToken supply * @param _componentPreviousBalance Pre-action component balance * @return Current component balance * @return Previous position unit * @return New position unit */ function calculateAndEditDefaultPosition( ISetToken _setToken, address _component, uint256 _setTotalSupply, uint256 _componentPreviousBalance ) external returns(uint256, uint256, uint256) { uint256 currentBalance = IERC20(_component).balanceOf(address(_setToken)); uint256 positionUnit = _setToken.getDefaultPositionRealUnit(_component).toUint256(); uint256 newTokenUnit; if (currentBalance > 0) { newTokenUnit = calculateDefaultEditPositionUnit( _setTotalSupply, _componentPreviousBalance, currentBalance, positionUnit ); } else { newTokenUnit = 0; } editDefaultPosition(_setToken, _component, newTokenUnit); return (currentBalance, positionUnit, newTokenUnit); } /** * Calculate the new position unit given total notional values pre and post executing an action that changes SetToken state * The intention is to make updates to the units without accidentally picking up airdropped assets as well. * * @param _setTokenSupply Supply of SetToken in precise units (10^18) * @param _preTotalNotional Total notional amount of component prior to executing action * @param _postTotalNotional Total notional amount of component after the executing action * @param _prePositionUnit Position unit of SetToken prior to executing action * @return New position unit */ function calculateDefaultEditPositionUnit( uint256 _setTokenSupply, uint256 _preTotalNotional, uint256 _postTotalNotional, uint256 _prePositionUnit ) public pure returns (uint256) { // If pre action total notional amount is greater then subtract post action total notional and calculate new position units uint256 airdroppedAmount = _preTotalNotional.sub(_prePositionUnit.preciseMul(_setTokenSupply)); return _postTotalNotional.sub(airdroppedAmount).preciseDiv(_setTokenSupply); } }
Unterschied finden