More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 38 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Settle Next Trad... | 16460966 | 176 days ago | IN | 0 ETH | 0.0000178 | ||||
Settle Next Trad... | 16460958 | 176 days ago | IN | 0 ETH | 0.000017 | ||||
Settle Next Trad... | 16460950 | 176 days ago | IN | 0 ETH | 0.00008261 | ||||
Withdraw From De... | 16459642 | 176 days ago | IN | 0 ETH | 0.00000793 | ||||
Settle | 16458376 | 176 days ago | IN | 0 ETH | 0.00002188 | ||||
Settle | 16458371 | 176 days ago | IN | 0 ETH | 0.00002204 | ||||
Settle | 16458367 | 176 days ago | IN | 0 ETH | 0.00002545 | ||||
Settle | 16458362 | 176 days ago | IN | 0 ETH | 0.0000247 | ||||
Settle Next Trad... | 16458342 | 176 days ago | IN | 0 ETH | 0.00004964 | ||||
Settle Next Trad... | 16458338 | 176 days ago | IN | 0 ETH | 0.00004189 | ||||
Settle Next Trad... | 16458334 | 176 days ago | IN | 0 ETH | 0.00004295 | ||||
Settle Next Trad... | 16458330 | 176 days ago | IN | 0 ETH | 0.00004715 | ||||
Settle | 16458062 | 176 days ago | IN | 0 ETH | 0.00001541 | ||||
Settle | 16458056 | 176 days ago | IN | 0 ETH | 0.00002374 | ||||
Settle | 16458051 | 176 days ago | IN | 0 ETH | 0.00001959 | ||||
Settle | 16458046 | 176 days ago | IN | 0 ETH | 0.00002192 | ||||
Settle | 16458041 | 176 days ago | IN | 0 ETH | 0.00002689 | ||||
Settle | 16458037 | 176 days ago | IN | 0 ETH | 0.00002234 | ||||
Settle | 16458025 | 176 days ago | IN | 0 ETH | 0.00002538 | ||||
Settle | 16458020 | 176 days ago | IN | 0 ETH | 0.00002419 | ||||
Settle | 16458017 | 176 days ago | IN | 0 ETH | 0.00001811 | ||||
Settle | 16458012 | 176 days ago | IN | 0 ETH | 0.000019 | ||||
Settle | 16458007 | 176 days ago | IN | 0 ETH | 0.00002374 | ||||
Settle | 16458003 | 176 days ago | IN | 0 ETH | 0.00002356 | ||||
Settle | 16457999 | 176 days ago | IN | 0 ETH | 0.00002185 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
14907307 | 230 days ago | 2 wei | ||||
14907307 | 230 days ago | 2 wei | ||||
14907306 | 230 days ago | 2 wei | ||||
14907306 | 230 days ago | 2 wei | ||||
14907304 | 230 days ago | 2 wei | ||||
14907304 | 230 days ago | 2 wei | ||||
14907303 | 230 days ago | 2 wei | ||||
14907303 | 230 days ago | 2 wei | ||||
14907302 | 230 days ago | 2 wei | ||||
14907302 | 230 days ago | 2 wei | ||||
14907301 | 230 days ago | 2 wei | ||||
14907301 | 230 days ago | 2 wei | ||||
14907299 | 230 days ago | 2 wei | ||||
14907299 | 230 days ago | 2 wei | ||||
14907298 | 230 days ago | 2 wei | ||||
14907298 | 230 days ago | 2 wei | ||||
14907297 | 230 days ago | 2 wei | ||||
14907297 | 230 days ago | 2 wei | ||||
14907295 | 230 days ago | 2 wei | ||||
14907295 | 230 days ago | 2 wei | ||||
14907294 | 230 days ago | 2 wei | ||||
14907294 | 230 days ago | 2 wei | ||||
14907293 | 230 days ago | 2 wei | ||||
14907293 | 230 days ago | 2 wei | ||||
14907292 | 230 days ago | 2 wei |
Loading...
Loading
Contract Name:
PerpetualManagerProxy
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 400 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; import "@openzeppelin/contracts/proxy/Proxy.sol"; import "./PerpStorage.sol"; import "../interfaces/ILibraryEvents.sol"; import "../interfaces/IFunctionList.sol"; import "../../libraries/EnumerableBytes4Set.sol"; import "../../libraries/Utils.sol"; contract PerpetualManagerProxy is PerpStorage, Proxy, ILibraryEvents { using EnumerableBytes4Set for EnumerableBytes4Set.Bytes4Set; bytes32 private constant KEY_IMPLEMENTATION = keccak256("key.implementation"); bytes32 private constant KEY_OWNER = keccak256("key.proxy.owner"); event ProxyOwnershipTransferred(address indexed _oldOwner, address indexed _newOwner); event ImplementationChanged( bytes4 _sig, address indexed _oldImplementation, address indexed _newImplementation ); /** * @notice Set sender as an owner. */ constructor() { _setProxyOwner(msg.sender); } /** * @notice Throw error if called not by an owner. */ modifier onlyProxyOwner() { require(msg.sender == getProxyOwner(), "Proxy:access denied"); _; } function _implementation() internal view override returns (address) { address implementation = _getImplementation(msg.sig); require(implementation != address(0), "Proxy:Implementation not found"); return implementation; } function getImplementation(bytes4 _sig) external view returns (address) { return _getImplementation(_sig); } function _getImplementation(bytes4 _sig) internal view returns (address) { bytes32 key = keccak256(abi.encode(_sig, KEY_IMPLEMENTATION)); address implementation; // solhint-disable-next-line no-inline-assembly assembly { implementation := sload(key) } return implementation; } /// @dev to delete module deploy a dummy module with the same name in getFunctionList() as being deleted /// it will remove all previous implementation functions function setImplementation(address _impl) external onlyProxyOwner { _setImplementation(_impl, false); } ///@dev allows replacement of functions from other modules. Use only if you realize consequences. function setImplementationCrossModules(address _impl) external onlyProxyOwner { _setImplementation(_impl, true); } ///@param _impl module address ///@param replaceOtherModulesFuncs allow to replace functions of other modules, use with caution function _setImplementation(address _impl, bool replaceOtherModulesFuncs) internal { require(_impl != address(0), "invalid implementation address"); (bytes4[] memory functions, bytes32 moduleName) = IFunctionList(_impl).getFunctionList(); require(moduleName != bytes32(0), "Module name cannot be empty"); EnumerableBytes4Set.Bytes4Set storage moduleActiveFunctionsSet = moduleActiveFuncSignatureList[moduleName]; bool moduleIsBeingUpdated = moduleActiveFunctionsSet.length() > 0; uint256 length = functions.length; for (uint256 i = 0; i < length; i++) { bytes4 funcSig = functions[i]; if (!moduleActiveFunctionsSet.contains(functions[i])) { // if the function registered with another module address anotherModuleImplAddress = _getImplementation(funcSig); if (anotherModuleImplAddress != address(0)) { require(replaceOtherModulesFuncs, "cant replace modules funcs"); moduleActiveFuncSignatureList[ moduleAddressToModuleName[anotherModuleImplAddress] ].removeBytes4(funcSig); } moduleActiveFunctionsSet.addBytes4(functions[i]); } _setImplementation(functions[i], _impl); } /// remove functions of the previous module version if (moduleIsBeingUpdated) { bytes4[] memory moduleActiveFuncsArray = moduleActiveFunctionsSet.enumerate( 0, moduleActiveFunctionsSet.length() ); length = moduleActiveFuncsArray.length; for (uint256 i; i < length; i++) { bytes4 funcSig = moduleActiveFuncsArray[i]; if (_getImplementation(funcSig) != _impl) { _setImplementation(funcSig, address(0)); moduleActiveFunctionsSet.removeBytes4(funcSig); } } } moduleNameToAddress[moduleName] = _impl; moduleAddressToModuleName[_impl] = moduleName; } function getModuleImplementationAddress(string calldata _moduleName) external view returns (address) { return moduleNameToAddress[Utils.stringToBytes32(_moduleName)]; } function _setImplementation(bytes4 _sig, address _impl) internal { _checkClashing(_sig); emit ImplementationChanged(_sig, _getImplementation(_sig), _impl); bytes32 key = keccak256(abi.encode(_sig, KEY_IMPLEMENTATION)); // solhint-disable-next-line no-inline-assembly assembly { sstore(key, _impl) } } /** * @notice Set address of the owner. * @param _owner Address of the owner. * */ function setProxyOwner(address _owner) external onlyProxyOwner { _setProxyOwner(_owner); } function _setProxyOwner(address _owner) internal { require(_owner != address(0), "invalid proxy owner address"); emit ProxyOwnershipTransferred(getProxyOwner(), _owner); bytes32 key = KEY_OWNER; // solhint-disable-next-line no-inline-assembly assembly { sstore(key, _owner) } } /** * @notice Return address of the owner. * @return _owner Address of the owner. */ function getProxyOwner() public view returns (address _owner) { bytes32 key = KEY_OWNER; // solhint-disable-next-line no-inline-assembly assembly { _owner := sload(key) } } function _checkClashing(bytes4 _sig) internal pure { bytes4[] memory functionList = _getFunctionList(); uint256 length = functionList.length; for (uint256 i = 0; i < length; i++) { require(_sig != functionList[i], "function id already exists"); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function pause() external whenNotPaused onlyMaintainer { _pause(); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function unpause() external virtual whenPaused onlyMaintainer { _unpause(); } function _getFunctionList() internal pure returns (bytes4[] memory) { bytes4[] memory functionList = new bytes4[](8); functionList[0] = this.getImplementation.selector; functionList[1] = this.setImplementation.selector; functionList[2] = this.setImplementationCrossModules.selector; functionList[3] = this.getModuleImplementationAddress.selector; functionList[4] = this.setProxyOwner.selector; functionList[5] = this.getProxyOwner.selector; functionList[6] = this.pause.selector; functionList[7] = this.unpause.selector; return functionList; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internall call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overriden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) // D8X, 2022 pragma solidity 0.8.21; /** * This is a modified version of the OpenZeppelin ownable contract * Modifications * - instead of an owner, we have two actors: maintainer and governance * - maintainer can have certain priviledges but cannot transfer maintainer mandate * - governance can exchange maintainer and exchange itself * - renounceOwnership is removed * * * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Maintainable { address private _maintainer; address private _governance; event MaintainerTransferred(address indexed previousMaintainer, address indexed newMaintainer); event GovernanceTransferred(address indexed previousGovernance, address indexed newGovernance); /** * @dev Initializes the contract setting the deployer as the initial maintainer. */ constructor() { _transferMaintainer(msg.sender); _transferGovernance(msg.sender); } /** * @dev Returns the address of the current owner. */ function maintainer() public view virtual returns (address) { return _maintainer; } /** * @dev Returns the address of the governance. */ function governance() public view virtual returns (address) { return _governance; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyMaintainer() { require(maintainer() == msg.sender, "only maintainer"); _; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyGovernance() { require(governance() == msg.sender, "only governance"); _; } /** * @dev Transfers maintainer mandate of the contract to a new account (`newMaintainer`). * Can only be called by the governance. */ function transferMaintainer(address newMaintainer) public virtual { require(msg.sender == _governance, "only governance"); require(newMaintainer != address(0), "zero address"); _transferMaintainer(newMaintainer); } /** * @dev Transfers governance mandate of the contract to a new account (`newGovernance`). * Can only be called by the governance. */ function transferGovernance(address newGovernance) public virtual { require(msg.sender == _governance, "only governance"); require(newGovernance != address(0), "zero address"); _transferGovernance(newGovernance); } /** * @dev Transfers maintainer of the contract to a new account (`newMaintainer`). * Internal function without access restriction. */ function _transferMaintainer(address newMaintainer) internal virtual { address oldM = _maintainer; _maintainer = newMaintainer; emit MaintainerTransferred(oldM, newMaintainer); } /** * @dev Transfers governance of the contract to a new account (`newGovernance`). * Internal function without access restriction. */ function _transferGovernance(address newGovernance) internal virtual { address oldG = _governance; _governance = newGovernance; emit GovernanceTransferred(oldG, newGovernance); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; interface IShareTokenFactory { function createShareToken(uint8 _poolId, address _marginTokenAddr) external returns (address); }
// SPDX-License-Identifier: BSD-4-Clause /* * ABDK Math 64.64 Smart Contract Library. Copyright © 2019 by ABDK Consulting. * Author: Mikhail Vladimirov <[email protected]> */ pragma solidity 0.8.21; /** * Smart contract library of mathematical functions operating with signed * 64.64-bit fixed point numbers. Signed 64.64-bit fixed point number is * basically a simple fraction whose numerator is signed 128-bit integer and * denominator is 2^64. As long as denominator is always the same, there is no * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are * represented by int128 type holding only the numerator. */ library ABDKMath64x64 { /* * Minimum value signed 64.64-bit fixed point number may have. */ int128 private constant MIN_64x64 = -0x80000000000000000000000000000000; /* * Maximum value signed 64.64-bit fixed point number may have. */ int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; /** * Convert signed 256-bit integer number into signed 64.64-bit fixed point * number. Revert on overflow. * * @param x signed 256-bit integer number * @return signed 64.64-bit fixed point number */ function fromInt(int256 x) internal pure returns (int128) { require(x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF, "ABDK.fromInt"); return int128(x << 64); } /** * Convert signed 64.64 fixed point number into signed 64-bit integer number * rounding down. * * @param x signed 64.64-bit fixed point number * @return signed 64-bit integer number */ function toInt(int128 x) internal pure returns (int64) { return int64(x >> 64); } /** * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point * number. Revert on overflow. * * @param x unsigned 256-bit integer number * @return signed 64.64-bit fixed point number */ function fromUInt(uint256 x) internal pure returns (int128) { require(x <= 0x7FFFFFFFFFFFFFFF, "ABDK.fromUInt"); return int128(int256(x << 64)); } /** * Convert signed 64.64 fixed point number into unsigned 64-bit integer * number rounding down. Revert on underflow. * * @param x signed 64.64-bit fixed point number * @return unsigned 64-bit integer number */ function toUInt(int128 x) internal pure returns (uint64) { require(x >= 0, "ABDK.toUInt"); return uint64(uint128(x >> 64)); } /** * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point * number rounding down. Revert on overflow. * * @param x signed 128.128-bin fixed point number * @return signed 64.64-bit fixed point number */ function from128x128(int256 x) internal pure returns (int128) { int256 result = x >> 64; require(result >= MIN_64x64 && result <= MAX_64x64, "ABDK.from128x128"); return int128(result); } /** * Convert signed 64.64 fixed point number into signed 128.128 fixed point * number. * * @param x signed 64.64-bit fixed point number * @return signed 128.128 fixed point number */ function to128x128(int128 x) internal pure returns (int256) { return int256(x) << 64; } /** * Calculate x + y. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function add(int128 x, int128 y) internal pure returns (int128) { int256 result = int256(x) + y; require(result >= MIN_64x64 && result <= MAX_64x64, "ABDK.add"); return int128(result); } /** * Calculate x - y. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function sub(int128 x, int128 y) internal pure returns (int128) { int256 result = int256(x) - y; require(result >= MIN_64x64 && result <= MAX_64x64, "ABDK.sub"); return int128(result); } /** * Calculate x * y rounding down. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function mul(int128 x, int128 y) internal pure returns (int128) { int256 result = (int256(x) * y) >> 64; require(result >= MIN_64x64 && result <= MAX_64x64, "ABDK.mul"); return int128(result); } /** * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point * number and y is signed 256-bit integer number. Revert on overflow. * * @param x signed 64.64 fixed point number * @param y signed 256-bit integer number * @return signed 256-bit integer number */ function muli(int128 x, int256 y) internal pure returns (int256) { if (x == MIN_64x64) { require( y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF && y <= 0x1000000000000000000000000000000000000000000000000, "ABDK.muli-1" ); return -y << 63; } else { bool negativeResult = false; if (x < 0) { x = -x; negativeResult = true; } if (y < 0) { y = -y; // We rely on overflow behavior here negativeResult = !negativeResult; } uint256 absoluteResult = mulu(x, uint256(y)); if (negativeResult) { require( absoluteResult <= 0x8000000000000000000000000000000000000000000000000000000000000000, "ABDK.muli-2" ); return -int256(absoluteResult); // We rely on overflow behavior here } else { require( absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "ABDK.muli-3" ); return int256(absoluteResult); } } } /** * Calculate x * y rounding down, where x is signed 64.64 fixed point number * and y is unsigned 256-bit integer number. Revert on overflow. * * @param x signed 64.64 fixed point number * @param y unsigned 256-bit integer number * @return unsigned 256-bit integer number */ function mulu(int128 x, uint256 y) internal pure returns (uint256) { if (y == 0) return 0; require(x >= 0, "ABDK.mulu-1"); uint256 lo = (uint256(int256(x)) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64; uint256 hi = uint256(int256(x)) * (y >> 128); require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "ABDK.mulu-2"); hi <<= 64; require( hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, "ABDK.mulu-3" ); return hi + lo; } /** * Calculate x / y rounding towards zero. Revert on overflow or when y is * zero. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function div(int128 x, int128 y) internal pure returns (int128) { require(y != 0, "ABDK.div-1"); int256 result = (int256(x) << 64) / y; require(result >= MIN_64x64 && result <= MAX_64x64, "ABDK.div-2"); return int128(result); } /** * Calculate x / y rounding towards zero, where x and y are signed 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x signed 256-bit integer number * @param y signed 256-bit integer number * @return signed 64.64-bit fixed point number */ function divi(int256 x, int256 y) internal pure returns (int128) { require(y != 0, "ABDK.divi-1"); bool negativeResult = false; if (x < 0) { x = -x; // We rely on overflow behavior here negativeResult = true; } if (y < 0) { y = -y; // We rely on overflow behavior here negativeResult = !negativeResult; } uint128 absoluteResult = divuu(uint256(x), uint256(y)); if (negativeResult) { require(absoluteResult <= 0x80000000000000000000000000000000, "ABDK.divi-2"); return -int128(absoluteResult); // We rely on overflow behavior here } else { require(absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "ABDK.divi-3"); return int128(absoluteResult); // We rely on overflow behavior here } } /** * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x unsigned 256-bit integer number * @param y unsigned 256-bit integer number * @return signed 64.64-bit fixed point number */ function divu(uint256 x, uint256 y) internal pure returns (int128) { require(y != 0, "ABDK.divu-1"); uint128 result = divuu(x, y); require(result <= uint128(MAX_64x64), "ABDK.divu-2"); return int128(result); } /** * Calculate -x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function neg(int128 x) internal pure returns (int128) { require(x != MIN_64x64, "ABDK.neg"); return -x; } /** * Calculate |x|. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function abs(int128 x) internal pure returns (int128) { require(x != MIN_64x64, "ABDK.abs"); return x < 0 ? -x : x; } /** * Calculate 1 / x rounding towards zero. Revert on overflow or when x is * zero. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function inv(int128 x) internal pure returns (int128) { require(x != 0, "ABDK.inv-1"); int256 result = int256(0x100000000000000000000000000000000) / x; require(result >= MIN_64x64 && result <= MAX_64x64, "ABDK.inv-2"); return int128(result); } /** * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function avg(int128 x, int128 y) internal pure returns (int128) { return int128((int256(x) + int256(y)) >> 1); } /** * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down. * Revert on overflow or in case x * y is negative. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function gavg(int128 x, int128 y) internal pure returns (int128) { int256 m = int256(x) * int256(y); require(m >= 0, "ABDK.gavg-1"); require( m < 0x4000000000000000000000000000000000000000000000000000000000000000, "ABDK.gavg-2" ); return int128(sqrtu(uint256(m))); } /** * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number * and y is unsigned 256-bit integer number. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y uint256 value * @return signed 64.64-bit fixed point number */ function pow(int128 x, uint256 y) internal pure returns (int128) { bool negative = x < 0 && y & 1 == 1; uint256 absX = uint128(x < 0 ? -x : x); uint256 absResult; absResult = 0x100000000000000000000000000000000; if (absX <= 0x10000000000000000) { absX <<= 63; while (y != 0) { if (y & 0x1 != 0) { absResult = (absResult * absX) >> 127; } absX = (absX * absX) >> 127; if (y & 0x2 != 0) { absResult = (absResult * absX) >> 127; } absX = (absX * absX) >> 127; if (y & 0x4 != 0) { absResult = (absResult * absX) >> 127; } absX = (absX * absX) >> 127; if (y & 0x8 != 0) { absResult = (absResult * absX) >> 127; } absX = (absX * absX) >> 127; y >>= 4; } absResult >>= 64; } else { uint256 absXShift = 63; if (absX < 0x1000000000000000000000000) { absX <<= 32; absXShift -= 32; } if (absX < 0x10000000000000000000000000000) { absX <<= 16; absXShift -= 16; } if (absX < 0x1000000000000000000000000000000) { absX <<= 8; absXShift -= 8; } if (absX < 0x10000000000000000000000000000000) { absX <<= 4; absXShift -= 4; } if (absX < 0x40000000000000000000000000000000) { absX <<= 2; absXShift -= 2; } if (absX < 0x80000000000000000000000000000000) { absX <<= 1; absXShift -= 1; } uint256 resultShift; while (y != 0) { require(absXShift < 64, "ABDK.pow-1"); if (y & 0x1 != 0) { absResult = (absResult * absX) >> 127; resultShift += absXShift; if (absResult > 0x100000000000000000000000000000000) { absResult >>= 1; resultShift += 1; } } absX = (absX * absX) >> 127; absXShift <<= 1; if (absX >= 0x100000000000000000000000000000000) { absX >>= 1; absXShift += 1; } y >>= 1; } require(resultShift < 64, "ABDK.pow-2"); absResult >>= 64 - resultShift; } int256 result = negative ? -int256(absResult) : int256(absResult); require(result >= MIN_64x64 && result <= MAX_64x64, "ABDK.pow-3"); return int128(result); } /** * Calculate sqrt (x) rounding down. Revert if x < 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function sqrt(int128 x) internal pure returns (int128) { require(x >= 0, "ABDK.sqrt"); return int128(sqrtu(uint256(int256(x)) << 64)); } /** * Calculate binary logarithm of x. Revert if x <= 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function log_2(int128 x) internal pure returns (int128) { require(x > 0, "ABDK.log_2"); int256 msb; int256 xc = x; if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; } if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore int256 result = (msb - 64) << 64; uint256 ux = uint256(int256(x)) << uint256(127 - msb); for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) { ux *= ux; uint256 b = ux >> 255; ux >>= 127 + b; result += bit * int256(b); } return int128(result); } /** * Calculate natural logarithm of x. Revert if x <= 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function ln(int128 x) internal pure returns (int128) { unchecked { require(x > 0, "ABDK.ln"); return int128( int256((uint256(int256(log_2(x))) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF) >> 128) ); } } /** * Calculate binary exponent of x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function exp_2(int128 x) internal pure returns (int128) { require(x < 0x400000000000000000, "ABDK.exp_2-1"); // Overflow if (x < -0x400000000000000000) return 0; // Underflow uint256 result = 0x80000000000000000000000000000000; if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128; if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128; if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128; if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128; if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128; if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128; if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128; if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128; if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128; if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128; if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128; if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128; if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128; if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128; if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128; if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128; if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128; if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128; if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128; if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128; if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128; if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128; if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128; if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128; if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128; if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128; if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128; if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128; if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128; if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128; if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128; if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128; if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128; if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128; if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128; if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128; if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128; if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128; if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128; if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128; if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128; if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128; if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128; if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128; if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128; if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128; if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128; if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128; if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128; if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128; if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128; if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128; if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128; if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128; if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128; if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128; if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128; if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128; if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128; if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128; if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128; if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128; if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128; if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128; result >>= uint256(int256(63 - (x >> 64))); require(result <= uint256(int256(MAX_64x64)), "ABDK.exp_2-2"); return int128(int256(result)); } /** * Calculate natural exponent of x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function exp(int128 x) internal pure returns (int128) { require(x < 0x400000000000000000, "ABDK.exp"); // Overflow if (x < -0x400000000000000000) return 0; // Underflow return exp_2(int128((int256(x) * 0x171547652B82FE1777D0FFDA0D23A7D12) >> 128)); } /** * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x unsigned 256-bit integer number * @param y unsigned 256-bit integer number * @return unsigned 64.64-bit fixed point number */ function divuu(uint256 x, uint256 y) private pure returns (uint128) { require(y != 0, "ABDK.divuu-1"); uint256 result; if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y; else { uint256 msb = 192; uint256 xc = x >> 192; if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1); require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "ABDK.divuu-2"); uint256 hi = result * (y >> 128); uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); uint256 xh = x >> 192; uint256 xl = x << 64; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here lo = hi << 128; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here assert(xh == hi >> 128); result += xl / y; } require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "ABDK.divuu-3"); return uint128(result); } /** * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer * number. * * @param x unsigned 256-bit integer number * @return unsigned 128-bit integer number */ function sqrtu(uint256 x) private pure returns (uint128) { if (x == 0) return 0; else { uint256 xx = x; uint256 r = 1; if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; } if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; } if (xx >= 0x100000000) { xx >>= 32; r <<= 16; } if (xx >= 0x10000) { xx >>= 16; r <<= 8; } if (xx >= 0x100) { xx >>= 8; r <<= 4; } if (xx >= 0x10) { xx >>= 4; r <<= 2; } if (xx >= 0x8) { r <<= 1; } r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; // Seven iterations should be enough uint256 r1 = x / r; return uint128(r < r1 ? r : r1); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; import "./ABDKMath64x64.sol"; library ConverterDec18 { using ABDKMath64x64 for int128; /* * Minimum value signed 64.64-bit fixed point number may have. */ int128 private constant MIN_64x64 = -0x80000000000000000000000000000000; /* * Maximum value signed 64.64-bit fixed point number may have. */ int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; int256 private constant DECIMALS = 10**18; int128 private constant ONE_64x64 = 0x010000000000000000; int128 public constant HALF_TBPS = 92233720368548; //1e-5 * 0.5 * 2**64 // convert tenth of basis point to dec 18: uint256 public constant TBPSTODEC18 = 0x9184e72a000; // hex(10^18 * 10^-5)=(10^13) // convert tenth of basis point to ABDK 64x64: int128 public constant TBPSTOABDK = 0xa7c5ac471b48; // hex(2^64 * 10^-5) // convert two-digit integer reprentation to ABDK int128 public constant TDRTOABDK = 0x28f5c28f5c28f5c; // hex(2^64 * 10^-2) function tbpsToDec18(uint16 Vtbps) internal pure returns (uint256) { return TBPSTODEC18 * uint256(Vtbps); } function tbpsToABDK(uint16 Vtbps) internal pure returns (int128) { return int128(uint128(TBPSTOABDK) * uint128(Vtbps)); } function TDRToABDK(uint16 V2Tdr) internal pure returns (int128) { return int128(uint128(TDRTOABDK) * uint128(V2Tdr)); } function ABDKToTbps(int128 Vabdk) internal pure returns (uint16) { // add 0.5 * 1e-5 to ensure correct rounding to tenth of bps return uint16(uint128(Vabdk.add(HALF_TBPS) / TBPSTOABDK)); } function fromDec18(int256 x) internal pure returns (int128) { int256 result = (x * ONE_64x64) / DECIMALS; require(x >= MIN_64x64 && x <= MAX_64x64, "result out of range"); return int128(result); } function toDec18(int128 x) internal pure returns (int256) { return (int256(x) * DECIMALS) / ONE_64x64; } function toUDec18(int128 x) internal pure returns (uint256) { require(x >= 0, "negative value"); return uint256(toDec18(x)); } function toUDecN(int128 x, uint8 decimals) internal pure returns (uint256) { require(x >= 0, "negative value"); return uint256((int256(x) * int256(10**decimals)) / ONE_64x64); } function fromDecN(int256 x, uint8 decimals) internal pure returns (int128) { int256 result = (x * ONE_64x64) / int256(10**decimals); require(x >= MIN_64x64 && x <= MAX_64x64, "result out of range"); return int128(result); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; /** * @title Library for managing loan sets. * * @notice Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * Include with `using EnumerableBytes4Set for EnumerableBytes4Set.Bytes4Set;`. * */ library EnumerableBytes4Set { struct Bytes4Set { // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes4 => uint256) index; bytes4[] values; } /** * @notice Add a value to a set. O(1). * * @param set The set of values. * @param value The new value to add. * * @return False if the value was already in the set. */ function addBytes4(Bytes4Set storage set, bytes4 value) internal returns (bool) { if (!contains(set, value)) { set.values.push(value); set.index[value] = set.values.length; return true; } else { return false; } } /** * @notice Remove a value from a set. O(1). * * @param set The set of values. * @param value The value to remove. * * @return False if the value was not present in the set. */ function removeBytes4(Bytes4Set storage set, bytes4 value) internal returns (bool) { if (contains(set, value)) { uint256 toDeleteIndex = set.index[value] - 1; uint256 lastIndex = set.values.length - 1; /// If the element we're deleting is the last one, /// we can just remove it without doing a swap. if (lastIndex != toDeleteIndex) { bytes4 lastValue = set.values[lastIndex]; /// Move the last value to the index where the deleted value is. set.values[toDeleteIndex] = lastValue; /// Update the index for the moved value. set.index[lastValue] = toDeleteIndex + 1; // All indexes are 1-based } /// Delete the index entry for the deleted value. delete set.index[value]; /// Delete the old entry for the moved value. set.values.pop(); return true; } else { return false; } } /** * @notice Find out whether a value exists in the set. * * @param set The set of values. * @param value The value to find. * * @return True if the value is in the set. O(1). */ function contains(Bytes4Set storage set, bytes4 value) internal view returns (bool) { return set.index[value] != 0; } /** * @notice Get all set values. * * @param set The set of values. * @param start The offset of the returning set. * @param count The limit of number of values to return. * * @return output An array with all values in the set. O(N). * * @dev Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * WARNING: This function may run out of gas on large sets: use {length} and * {get} instead in these cases. */ function enumerate( Bytes4Set storage set, uint256 start, uint256 count ) internal view returns (bytes4[] memory output) { uint256 end = start + count; require(end >= start, "addition overflow"); end = set.values.length < end ? set.values.length : end; if (end == 0 || start >= end) { return output; } output = new bytes4[](end - start); for (uint256 i; i < end - start; i++) { output[i] = set.values[i + start]; } return output; } /** * @notice Get the legth of the set. * * @param set The set of values. * * @return the number of elements on the set. O(1). */ function length(Bytes4Set storage set) internal view returns (uint256) { return set.values.length; } /** * @notice Get an item from the set by its index. * * @dev Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. * * @param set The set of values. * @param index The index of the value to return. * * @return the element stored at position `index` in the set. O(1). */ function get(Bytes4Set storage set, uint256 index) internal view returns (bytes4) { return set.values[index]; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSetUpgradeable { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { require(set._values.length > index, "EnumerableSet: idx out of bounds"); return set._values[index]; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } function enumerate( AddressSet storage set, uint256 start, uint256 count ) internal view returns (address[] memory output) { uint256 end = start + count; require(end >= start, "addition overflow"); uint256 len = length(set); end = len < end ? len : end; if (end == 0 || start >= end) { return output; } output = new address[](end - start); for (uint256 i; i < end - start; i++) { output[i] = at(set, i + start); } return output; } function enumerateAll(AddressSet storage set) internal view returns (address[] memory output) { return enumerate(set, 0, length(set)); } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; library Utils { function stringToBytes32(string memory source) internal pure returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(source); if (tempEmptyStringTest.length == 0) { return 0x0; } assembly { result := mload(add(source, 32)) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "../../interface/IShareTokenFactory.sol"; import "../../libraries/ABDKMath64x64.sol"; import "./../functions/AMMPerpLogic.sol"; import "../../libraries/EnumerableSetUpgradeable.sol"; import "../../libraries/EnumerableBytes4Set.sol"; import "../../governance/Maintainable.sol"; /* solhint-disable max-states-count */ contract PerpStorage is Maintainable, Pausable, ReentrancyGuard { using ABDKMath64x64 for int128; using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet; using EnumerableBytes4Set for EnumerableBytes4Set.Bytes4Set; // enumerable map of bytes4 or addresses /** * @notice Perpetual state: * - INVALID: Uninitialized or not non-existent perpetual. * - INITIALIZING: Only when LiquidityPoolData.isRunning == false. Traders cannot perform operations. * - NORMAL: Full functional state. Traders are able to perform all operations. * - EMERGENCY: Perpetual is unsafe and the perpetual needs to be settled. * - SETTLE: Perpetual ready to be settled * - CLEARED: All margin accounts are cleared. Traders can withdraw remaining margin balance. */ enum PerpetualState { INVALID, INITIALIZING, NORMAL, EMERGENCY, SETTLE, CLEARED } // margin and liquidity pool are held in 'collateral currency' which can be either of // quote currency, base currency, or quanto currency // solhint-disable-next-line const-name-snakecase int128 internal constant ONE_64x64 = 0x10000000000000000; // 2^64 int128 internal constant FUNDING_INTERVAL_SEC = 0x70800000000000000000; //3600 * 8 * 0x10000000000000000 = 8h in seconds scaled by 2^64 for ABDKMath64x64 int128 internal constant MIN_NUM_LOTS_PER_POSITION = 0x0a0000000000000000; // 10, minimal position size in number of lots uint8 internal constant MASK_ORDER_CANCELLED = 0x1; uint8 internal constant MASK_ORDER_EXECUTED = 0x2; // at target, 1% of missing amount is transferred // at every rebalance uint8 internal iPoolCount; // delay required for trades to mitigate oracle front-running in seconds uint8 internal iTradeDelaySec; address internal ammPerpLogic; IShareTokenFactory internal shareTokenFactory; //pool id (incremental index, starts from 1) => pool data mapping(uint8 => LiquidityPoolData) internal liquidityPools; //perpetual id => pool id mapping(uint24 => uint8) internal perpetualPoolIds; address internal orderBookFactory; /** * @notice Data structure to store oracle price data. */ struct PriceTimeData { int128 fPrice; uint64 time; } /** * @notice Data structure to store user margin information. */ struct MarginAccount { int128 fLockedInValueQC; // unrealized value locked-in when trade occurs int128 fCashCC; // cash in collateral currency (base, quote, or quanto) int128 fPositionBC; // position in base currency (e.g., 1 BTC for BTCUSD) int128 fUnitAccumulatedFundingStart; // accumulated funding rate uint64 iLastOpenTimestamp; // timestamp in seconds when the position was last opened/increased uint16 feeTbps; // exchange fee in tenth of a basis point uint16 brokerFeeTbps; // broker fee in tenth of a basis point bytes16 positionId; // unique id for the position (for given trader, and perpetual). Current position, zero otherwise. } /** * @notice Store information for a given perpetual market. */ struct PerpetualData { // ------ 0 uint8 poolId; uint24 id; int32 fInitialMarginRate; //parameter: initial margin int32 fSigma2; // parameter: volatility of base-quote pair uint32 iLastFundingTime; //timestamp since last funding rate payment uint32 iLastSettlementPriceUpdateTimestamp; // timestamp when last price was observed happened uint32 iLastPriceJumpTimestamp; // timestamp when last price jump happened int32 fMaintenanceMarginRate; // parameter: maintenance margin PerpetualState state; // Perpetual AMM state AMMPerpLogic.CollateralCurrency eCollateralCurrency; //parameter: in what currency is the collateral held? uint16 minimalSpreadTbps; //parameter: minimal spread between long and short perpetual price // ------ 1 bytes4 S2BaseCCY; //base currency of S2 bytes4 S2QuoteCCY; //quote currency of S2 uint16 incentiveSpreadTbps; //parameter: maximum spread added to the PD uint16 jumpSpreadTbps; // spread that is adjusted based on price jumps bytes4 S3BaseCCY; //base currency of S3 bytes4 S3QuoteCCY; //quote currency of S3 int32 fSigma3; // parameter: volatility of quanto-quote pair int32 fRho23; // parameter: correlation of quanto/base returns uint16 liquidationPenaltyRateTbps; //parameter: penalty if AMM closes the position and not the trader //------- 2 PriceTimeData currentMarkPremiumRate; //relative diff to index price EMA, used for markprice. //------- 3 int128 premiumRatesEMA; // EMA of premium rate int128 fUnitAccumulatedFunding; //accumulated funding in collateral currency //------- 4 int128 fOpenInterest; //open interest is the larger of the amount of long and short positions in base currency int128 fTargetAMMFundSize; //target liquidity pool funds to allocate to the AMM //------- 5 int128 fCurrentTraderExposureEMA; // trade amounts (storing absolute value) int128 fCurrentFundingRate; // current instantaneous funding rate //------- 6 int128 fLotSizeBC; //parameter: minimal trade unit (in base currency) to avoid dust positions int128 fReferralRebateCC; //parameter: referall rebate in collateral currency //------- 7 int128 fTargetDFSize; // target default fund size int128 fkStar; // signed trade size that minimizes the AMM risk //------- 8 int128 fAMMTargetDD; // parameter: target distance to default (=inverse of default probability) int128 fAMMMinSizeCC; // parameter: minimal size of AMM pool, regardless of current exposure //------- 9 int128 fMinimalTraderExposureEMA; // parameter: minimal value for fCurrentTraderExposureEMA that we don't want to undershoot int128 fMinimalAMMExposureEMA; // parameter: minimal abs value for fCurrentAMMExposureEMA that we don't want to undershoot //------- 10 int128 fSettlementS3PriceData; //quanto index int128 fSettlementS2PriceData; //base-quote pair. Used as last price in normal state. //------- 11 int128 fTotalMarginBalance; //calculated for settlement, in collateral currency int32 fMarkPriceEMALambda; // parameter: Lambda parameter for EMA used in mark-price for funding rates int32 fFundingRateClamp; // parameter: funding rate clamp between which we charge 1bps int32 fMaximalTradeSizeBumpUp; // parameter: >1, users can create a maximal position of size fMaximalTradeSizeBumpUp*fCurrentAMMExposureEMA uint32 iLastTargetPoolSizeTime; //timestamp (seconds) since last update of fTargetDFSize and fTargetAMMFundSize //------- 12 int32 fDFCoverNRate; // parameter: cover-n rule for default fund. E.g., fDFCoverNRate=0.05 -> we try to cover 5% of active accounts with default fund //------- int128[2] fStressReturnS3; // parameter: negative and positive stress returns for quanto-quote asset int128[2] fDFLambda; // parameter: EMA lambda for AMM and trader exposure K,k: EMA*lambda + (1-lambda)*K. 0 regular lambda, 1 if current value exceeds past int128[2] fCurrentAMMExposureEMA; // 0: negative aggregated exposure (storing negative value), 1: positive int128[2] fStressReturnS2; // parameter: negative and positive stress returns for base-quote asset // ----- } address internal oracleFactoryAddress; // users mapping(uint24 => EnumerableSetUpgradeable.AddressSet) internal activeAccounts; //perpetualId => traderAddressSet // accounts mapping(uint24 => mapping(address => MarginAccount)) internal marginAccounts; // delegates mapping(address => address) internal delegates; // broker maps: poolId -> brokeraddress-> lots contributed // contains non-zero entries for brokers. Brokers pay default fund contributions. mapping(uint8 => mapping(address => uint32)) internal brokerMap; struct LiquidityPoolData { bool isRunning; // state uint8 iPerpetualCount; // state uint8 id; // parameter: index, starts from 1 int32 fCeilPnLShare; // parameter: cap on the share of PnL allocated to liquidity providers uint8 marginTokenDecimals; // parameter: decimals of margin token, inferred from token contract uint16 iTargetPoolSizeUpdateTime; //parameter: timestamp in seconds. How often we update the pool's target size address marginTokenAddress; //parameter: address of the margin token // ----- uint64 prevAnchor; // state: keep track of timestamp since last withdrawal was initiated int128 fRedemptionRate; // state: used for settlement in case of AMM default address shareTokenAddress; // parameter // ----- int128 fPnLparticipantsCashCC; // state: addLiquidity/withdrawLiquidity + profit/loss - rebalance int128 fTargetAMMFundSize; // state: target liquidity for all perpetuals in pool (sum) // ----- int128 fDefaultFundCashCC; // state: profit/loss int128 fTargetDFSize; // state: target default fund size for all perpetuals in pool // ----- int128 fBrokerCollateralLotSize; // param:how much collateral do brokers deposit when providing "1 lot" (not trading lot) uint128 prevTokenAmount; // state // ----- uint128 nextTokenAmount; // state uint128 totalSupplyShareToken; // state // ----- int128 fBrokerFundCashCC; // state: amount of cash in broker fund } address internal treasuryAddress; // address for the protocol treasury //pool id => perpetual id list mapping(uint8 => uint24[]) internal perpetualIds; //pool id => perpetual id => data mapping(uint8 => mapping(uint24 => PerpetualData)) internal perpetuals; /// @dev flag whether MarginTradeOrder was already executed or cancelled mapping(bytes32 => uint8) internal executedOrCancelledOrders; //proxy mapping(bytes32 => EnumerableBytes4Set.Bytes4Set) internal moduleActiveFuncSignatureList; mapping(bytes32 => address) internal moduleNameToAddress; mapping(address => bytes32) internal moduleAddressToModuleName; } /* solhint-enable max-states-count */
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; import "../../libraries/ABDKMath64x64.sol"; import "../../libraries/ConverterDec18.sol"; import "../../perpetual/interfaces/IAMMPerpLogic.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract AMMPerpLogic is Ownable, IAMMPerpLogic { using ABDKMath64x64 for int128; /* solhint-disable const-name-snakecase */ int128 internal constant ONE_64x64 = 0x10000000000000000; // 2^64 int128 internal constant TWO_64x64 = 0x20000000000000000; // 2*2^64 int128 internal constant FOUR_64x64 = 0x40000000000000000; //4*2^64 int128 internal constant HALF_64x64 = 0x8000000000000000; //0.5*2^64 int128 internal constant TWENTY_64x64 = 0x140000000000000000; //20*2^64 int128 private constant CDF_CONST_0 = 0x023a6ce358298c; int128 private constant CDF_CONST_1 = -0x216c61522a6f3f; int128 private constant CDF_CONST_2 = 0xc9320d9945b6c3; int128 private constant CDF_CONST_3 = -0x01bcfd4bf0995aaf; int128 private constant CDF_CONST_4 = -0x086de76427c7c501; int128 private constant CDF_CONST_5 = 0x749741d084e83004; int128 private constant CDF_CONST_6 = 0xcc42299ea1b28805; int128 private constant CDF_CONST_7 = 0x0281b263fec4e0a007; int128 private constant EXPM1_Q0 = 0x0a26c00000000000000000; int128 private constant EXPM1_Q1 = 0x0127500000000000000000; int128 private constant EXPM1_P0 = 0x0513600000000000000000; int128 private constant EXPM1_P1 = 0x27600000000000000000; int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; /* solhint-enable const-name-snakecase */ enum CollateralCurrency { QUOTE, BASE, QUANTO } struct AMMVariables { // all variables are // signed 64.64-bit fixed point number int128 fLockedValue1; // L1 in quote currency int128 fPoolM1; // M1 in quote currency int128 fPoolM2; // M2 in base currency int128 fPoolM3; // M3 in quanto currency int128 fAMM_K2; // AMM exposure (positive if trader long) int128 fCurrentTraderExposureEMA; // current average unsigned trader exposure } struct MarketVariables { int128 fIndexPriceS2; // base index int128 fIndexPriceS3; // quanto index int128 fSigma2; // standard dev of base currency int128 fSigma3; // standard dev of quanto currency int128 fRho23; // correlation base/quanto currency } /** * Calculate a half-spread that depends on past jumps * @dev if more than 30 seconds the function returns minimal spread. * Accuracy of this is obviously parametrization dependent * @param _jumpTbps jump spread based on return of oracle price * @param _minimalSpreadTbps minimal spread the EMA converges to * @param _numSecSinceJump time passed since jump * @param _fLambda convergence * @return fHalfSpread (int128) */ function volatilitySpread( uint16 _jumpTbps, uint16 _minimalSpreadTbps, uint256 _numSecSinceJump, int128 _fLambda ) external pure returns (int128) { // v0 = (1-L**numBlocksSinceJump) * minimalSpread // v1 = jump*L**numBlocksSinceJump // return v0+v1 if (_numSecSinceJump > 30) { return ConverterDec18.tbpsToABDK(_minimalSpreadTbps); } return _emaWithTimeJumps(_minimalSpreadTbps, _jumpTbps, _fLambda, _numSecSinceJump); } /** * Calculate the penalty for closing a position before the holding period is satisfied * @dev The penalty is 8 bps for same second and decreases exponentially to 0 at 32 seconds * @param _secondsSinceLastOpen how much time passed since the position was opened * @param _fLambda lambda for the exponential decay: penalty_nSeconds ~ lambda ^ nSeconds * @return penalty Penalty in tbps */ function holdingPeriodPenalty(uint256 _secondsSinceLastOpen, int128 _fLambda) external pure returns (uint16 penalty) { if (_secondsSinceLastOpen > 32) { return 0; } penalty = ConverterDec18.ABDKToTbps( _emaWithTimeJumps(0, 80, _fLambda, _secondsSinceLastOpen) ); } /** * Calculate a EWMA when the last observation happened n periods ago * @dev Given is x_t = (1 - lambda) * mean + lambda * x_t-1, and x_0 = _newObs * it returns the value of x_deltaTime * @param _mean long term mean * @param _newObs observation deltaTime periods ago * @param _fLambda lambda of the EWMA * @param _deltaTime number of periods elapsed * @return result EWMA at deltaPeriods */ function _emaWithTimeJumps( uint16 _mean, uint16 _newObs, int128 _fLambda, uint256 _deltaTime ) internal pure returns (int128 result) { _fLambda = _fLambda.pow(_deltaTime); result = ConverterDec18.tbpsToABDK(_mean).mul(ONE_64x64.sub(_fLambda)); result = result.add(_fLambda.mul(ConverterDec18.tbpsToABDK(_newObs))); } /** * Calculate the normal CDF value of _fX, i.e., * k=P(X<=_fX), for X~normal(0,1) * The approximation is of the form * Phi(x) = 1 - phi(x) / (x + exp(p(x))), * where p(x) is a polynomial of degree 6 * @param _fX signed 64.64-bit fixed point number * @return fY approximated normal-cdf evaluated at X */ function _normalCDF(int128 _fX) internal pure returns (int128 fY) { bool isNegative = _fX < 0; if (isNegative) { _fX = _fX.neg(); } if (_fX > FOUR_64x64) { fY = int128(0); } else { fY = _fX.mul(CDF_CONST_0).add(CDF_CONST_1); fY = _fX.mul(fY).add(CDF_CONST_2); fY = _fX.mul(fY).add(CDF_CONST_3); fY = _fX.mul(fY).add(CDF_CONST_4); fY = _fX.mul(fY).add(CDF_CONST_5).mul(_fX).neg().exp(); fY = fY.mul(CDF_CONST_6).add(_fX); fY = _fX.mul(_fX).mul(HALF_64x64).neg().exp().div(CDF_CONST_7).div(fY); } if (!isNegative) { fY = ONE_64x64.sub(fY); } return fY; } /** * Calculate the target size for the default fund * * @param _fK2AMM signed 64.64-bit fixed point number, Conservative negative[0]/positive[1] AMM exposure * @param _fk2Trader signed 64.64-bit fixed point number, Conservative (absolute) trader exposure * @param _fCoverN signed 64.64-bit fixed point number, cover-n rule for default fund parameter * @param fStressRet2 signed 64.64-bit fixed point number, negative[0]/positive[1] stress returns for base/quote pair * @param fStressRet3 signed 64.64-bit fixed point number, negative[0]/positive[1] stress returns for quanto/quote currency * @param fIndexPrices signed 64.64-bit fixed point number, spot price for base/quote[0] and quanto/quote[1] pairs * @param _eCCY enum that specifies in which currency the collateral is held: QUOTE, BASE, QUANTO * @return approximated normal-cdf evaluated at X */ function calculateDefaultFundSize( int128[2] memory _fK2AMM, int128 _fk2Trader, int128 _fCoverN, int128[2] memory fStressRet2, int128[2] memory fStressRet3, int128[2] memory fIndexPrices, AMMPerpLogic.CollateralCurrency _eCCY ) external pure override returns (int128) { require(_fK2AMM[0] < 0, "_fK2AMM[0] must be negative"); require(_fK2AMM[1] > 0, "_fK2AMM[1] must be positive"); require(_fk2Trader > 0, "_fk2Trader must be positive"); int128[2] memory fEll; // downward stress scenario fEll[0] = (_fK2AMM[0].abs().add(_fk2Trader.mul(_fCoverN))).mul( ONE_64x64.sub((fStressRet2[0].exp())) ); // upward stress scenario fEll[1] = (_fK2AMM[1].abs().add(_fk2Trader.mul(_fCoverN))).mul( (fStressRet2[1].exp().sub(ONE_64x64)) ); int128 fIstar; if (_eCCY == AMMPerpLogic.CollateralCurrency.BASE) { fIstar = fEll[0].div(fStressRet2[0].exp()); int128 fI2 = fEll[1].div(fStressRet2[1].exp()); if (fI2 > fIstar) { fIstar = fI2; } } else if (_eCCY == AMMPerpLogic.CollateralCurrency.QUANTO) { fIstar = fEll[0].div(fStressRet3[0].exp()); int128 fI2 = fEll[1].div(fStressRet3[1].exp()); if (fI2 > fIstar) { fIstar = fI2; } fIstar = fIstar.mul(fIndexPrices[0].div(fIndexPrices[1])); } else { assert(_eCCY == AMMPerpLogic.CollateralCurrency.QUOTE); if (fEll[0] > fEll[1]) { fIstar = fEll[0].mul(fIndexPrices[0]); } else { fIstar = fEll[1].mul(fIndexPrices[0]); } } return fIstar; } /** * Calculate the risk neutral Distance to Default (Phi(DD)=default probability) when * there is no quanto currency collateral. * We assume r=0 everywhere. * The underlying distribution is log-normal, hence the log below. * All variables are 64.64-bit fixed point number (or struct thereof) * @param fSigma2 current Market variables (price¶ms) * @param _fSign signed 64.64-bit fixed point number, sign of denominator of distance to default * @return _fThresh signed 64.64-bit fixed point number, number for which the log is the unnormalized distance to default */ function _calculateRiskNeutralDDNoQuanto( int128 fSigma2, int128 _fSign, int128 _fThresh ) internal pure returns (int128) { require(_fThresh > 0, "argument to log must be >0"); int128 _fLogTresh = _fThresh.ln(); int128 fSigma2_2 = fSigma2.mul(fSigma2); int128 fMean = fSigma2_2.div(TWO_64x64).neg(); int128 fDistanceToDefault = ABDKMath64x64.sub(_fLogTresh, fMean).div(fSigma2); // because 1-Phi(x) = Phi(-x) we change the sign if _fSign<0 // now we would like to get the normal cdf of that beast if (_fSign < 0) { fDistanceToDefault = fDistanceToDefault.neg(); } return fDistanceToDefault; } /** * Calculate the standard deviation for the random variable * evolving when quanto currencies are involved. * We assume r=0 everywhere. * All variables are 64.64-bit fixed point number (or struct thereof) * @param _mktVars current Market variables (price¶ms) * @param _fC3 signed 64.64-bit fixed point number current AMM/Market variables * @param _fC3_2 signed 64.64-bit fixed point number, squared fC3 * @return fSigmaZ standard deviation, 64.64-bit fixed point number */ function _calculateStandardDeviationQuanto( MarketVariables memory _mktVars, int128 _fC3, int128 _fC3_2 ) internal pure returns (int128 fSigmaZ) { // fVarA = (exp(sigma2^2) - 1) int128 fVarA = _mktVars.fSigma2.mul(_mktVars.fSigma2); // fVarB = 2*(exp(sigma2*sigma3*rho) - 1) int128 fVarB = _mktVars.fSigma2.mul(_mktVars.fSigma3).mul(_mktVars.fRho23).mul(TWO_64x64); // fVarC = exp(sigma3^2) - 1 int128 fVarC = _mktVars.fSigma3.mul(_mktVars.fSigma3); // sigmaZ = fVarA*C^2 + fVarB*C + fVarC fSigmaZ = fVarA.mul(_fC3_2).add(fVarB.mul(_fC3)).add(fVarC).sqrt(); } /** * Calculate the risk neutral Distance to Default (Phi(DD)=default probability) when * presence of quanto currency collateral. * * We approximate the distribution with a normal distribution * We assume r=0 everywhere. * All variables are 64.64-bit fixed point number * @param _ammVars current AMM/Market variables * @param _mktVars current Market variables (price¶ms) * @param _fSign 64.64-bit fixed point number, current AMM/Market variables * @return fDistanceToDefault signed 64.64-bit fixed point number */ function _calculateRiskNeutralDDWithQuanto( AMMVariables memory _ammVars, MarketVariables memory _mktVars, int128 _fSign, int128 _fThresh ) internal pure returns (int128 fDistanceToDefault) { require(_fSign > 0, "no sign in quanto case"); // 1) Calculate C3 int128 fC3 = _mktVars.fIndexPriceS2.mul(_ammVars.fPoolM2.sub(_ammVars.fAMM_K2)).div( _ammVars.fPoolM3.mul(_mktVars.fIndexPriceS3) ); int128 fC3_2 = fC3.mul(fC3); // 2) Calculate Variance int128 fSigmaZ = _calculateStandardDeviationQuanto(_mktVars, fC3, fC3_2); // 3) Calculate mean int128 fMean = fC3.add(ONE_64x64); // 4) Distance to default fDistanceToDefault = _fThresh.sub(fMean).div(fSigmaZ); } function calculateRiskNeutralPD( AMMVariables memory _ammVars, MarketVariables memory _mktVars, int128 _fTradeAmount, bool _withCDF ) external view virtual override returns (int128, int128) { return _calculateRiskNeutralPD(_ammVars, _mktVars, _fTradeAmount, _withCDF); } /** * Calculate the risk neutral default probability (>=0). * Function decides whether pricing with or without quanto CCY is chosen. * We assume r=0 everywhere. * All variables are 64.64-bit fixed point number (or struct thereof) * @param _ammVars current AMM variables. * @param _mktVars current Market variables (price¶ms) * @param _fTradeAmount Trade amount (can be 0), hence amounts k2 are not already factored in * that is, function will set K2:=K2+k2, L1:=L1+k2*s2 (k2=_fTradeAmount) * @param _withCDF bool. If false, the normal-cdf is not evaluated (in case the caller is only * interested in the distance-to-default, this saves calculations) * @return (default probabilit, distance to default) ; 64.64-bit fixed point numbers */ function _calculateRiskNeutralPD( AMMVariables memory _ammVars, MarketVariables memory _mktVars, int128 _fTradeAmount, bool _withCDF ) internal pure returns (int128, int128) { int128 dL = _fTradeAmount.mul(_mktVars.fIndexPriceS2); int128 dK = _fTradeAmount; _ammVars.fLockedValue1 = _ammVars.fLockedValue1.add(dL); _ammVars.fAMM_K2 = _ammVars.fAMM_K2.add(dK); // -L1 - k*s2 - M1 int128 fNumerator = (_ammVars.fLockedValue1.neg()).sub(_ammVars.fPoolM1); // s2*(M2-k2-K2) if no quanto, else M3 * s3 int128 fDenominator = _ammVars.fPoolM3 == 0 ? (_ammVars.fPoolM2.sub(_ammVars.fAMM_K2)).mul(_mktVars.fIndexPriceS2) : _ammVars.fPoolM3.mul(_mktVars.fIndexPriceS3); // handle edge sign cases first int128 fThresh; if (_ammVars.fPoolM3 == 0) { if (fNumerator < 0) { if (fDenominator >= 0) { // P( den * exp(x) < 0) = 0 return (int128(0), TWENTY_64x64.neg()); } else { // num < 0 and den < 0, and P(exp(x) > infty) = 0 int256 result = (int256(fNumerator) << 64) / fDenominator; if (result > MAX_64x64) { return (int128(0), TWENTY_64x64.neg()); } fThresh = int128(result); } } else if (fNumerator > 0) { if (fDenominator <= 0) { // P( exp(x) >= 0) = 1 return (int128(ONE_64x64), TWENTY_64x64); } else { // num > 0 and den > 0, and P(exp(x) < infty) = 1 int256 result = (int256(fNumerator) << 64) / fDenominator; if (result > MAX_64x64) { return (int128(ONE_64x64), TWENTY_64x64); } fThresh = int128(result); } } else { return fDenominator >= 0 ? (int128(0), TWENTY_64x64.neg()) : (int128(ONE_64x64), TWENTY_64x64); } } else { // denom is O(M3 * S3), div should not overflow fThresh = fNumerator.div(fDenominator); } // if we're here fDenominator !=0 and fThresh did not overflow // sign tells us whether we consider norm.cdf(f(threshold)) or 1-norm.cdf(f(threshold)) // we recycle fDenominator to store the sign since it's no longer used fDenominator = fDenominator < 0 ? ONE_64x64.neg() : ONE_64x64; int128 dd = _ammVars.fPoolM3 == 0 ? _calculateRiskNeutralDDNoQuanto(_mktVars.fSigma2, fDenominator, fThresh) : _calculateRiskNeutralDDWithQuanto(_ammVars, _mktVars, fDenominator, fThresh); int128 q; if (_withCDF) { q = _normalCDF(dd); } return (q, dd); } /** * Calculate additional/non-risk based slippage. * Ensures slippage is bounded away from zero for small trades, * and plateaus for larger-than-average trades, so that price becomes risk based. * * All variables are 64.64-bit fixed point number (or struct thereof) * @param _ammVars current AMM variables - we need the current average exposure per trader * @param _fTradeAmount 64.64-bit fixed point number, signed size of trade * @return 64.64-bit fixed point number, a number between minus one and one */ function _calculateBoundedSlippage(AMMVariables memory _ammVars, int128 _fTradeAmount) internal pure returns (int128) { int128 fTradeSizeEMA = _ammVars.fCurrentTraderExposureEMA; int128 fSlippageSize = ONE_64x64; if (_fTradeAmount.abs() < fTradeSizeEMA) { fSlippageSize = fSlippageSize.sub(_fTradeAmount.abs().div(fTradeSizeEMA)); fSlippageSize = ONE_64x64.sub(fSlippageSize.mul(fSlippageSize)); } return _fTradeAmount > 0 ? fSlippageSize : fSlippageSize.neg(); } /** * Calculate AMM price. * * All variables are 64.64-bit fixed point number (or struct thereof) * @param _ammVars current AMM variables. * @param _mktVars current Market variables (price¶ms) * Trader amounts k2 must already be factored in * that is, K2:=K2+k2, L1:=L1+k2*s2 * @param _fTradeAmount 64.64-bit fixed point number, signed size of trade * @param _fHBidAskSpread half bid-ask spread, 64.64-bit fixed point number * @return 64.64-bit fixed point number, AMM price */ function calculatePerpetualPrice( AMMVariables memory _ammVars, MarketVariables memory _mktVars, int128 _fTradeAmount, int128 _fHBidAskSpread, int128 _fIncentiveSpread ) external view virtual override returns (int128) { // add minimal spread in quote currency _fHBidAskSpread = _fTradeAmount > 0 ? _fHBidAskSpread : _fHBidAskSpread.neg(); if (_fTradeAmount == 0) { _fHBidAskSpread = 0; } // get risk-neutral default probability (always >0) { int128 fQ; int128 dd; int128 fkStar = _ammVars.fPoolM2.sub(_ammVars.fAMM_K2); (fQ, dd) = _calculateRiskNeutralPD(_ammVars, _mktVars, _fTradeAmount, true); if (_ammVars.fPoolM3 != 0) { // amend K* (see whitepaper) int128 nominator = _mktVars.fRho23.mul(_mktVars.fSigma2.mul(_mktVars.fSigma3)); int128 denom = _mktVars.fSigma2.mul(_mktVars.fSigma2); int128 h = nominator.div(denom).mul(_ammVars.fPoolM3); h = h.mul(_mktVars.fIndexPriceS3).div(_mktVars.fIndexPriceS2); fkStar = fkStar.add(h); } // decide on sign of premium if (_fTradeAmount < fkStar) { fQ = fQ.neg(); } // no rebate if exposure increases if (_fTradeAmount > 0 && _ammVars.fAMM_K2 > 0) { fQ = fQ > 0 ? fQ : int128(0); } else if (_fTradeAmount < 0 && _ammVars.fAMM_K2 < 0) { fQ = fQ < 0 ? fQ : int128(0); } // handle discontinuity at zero if ( _fTradeAmount == 0 && ((fQ < 0 && _ammVars.fAMM_K2 > 0) || (fQ > 0 && _ammVars.fAMM_K2 < 0)) ) { fQ = fQ.div(TWO_64x64); } _fHBidAskSpread = _fHBidAskSpread.add(fQ); } // get additional slippage if (_fTradeAmount != 0) { _fIncentiveSpread = _fIncentiveSpread.mul( _calculateBoundedSlippage(_ammVars, _fTradeAmount) ); _fHBidAskSpread = _fHBidAskSpread.add(_fIncentiveSpread); } // s2*(1 + sign(qp-q)*q + sign(k)*minSpread) return _mktVars.fIndexPriceS2.mul(ONE_64x64.add(_fHBidAskSpread)); } /** * Calculate target collateral M1 (Quote Currency), when no M2, M3 is present * The targeted default probability is expressed using the inverse * _fTargetDD = Phi^(-1)(targetPD) * _fK2 in absolute terms must be 'reasonably large' * sigma3, rho23, IndexpriceS3 not relevant. * @param _fK2 signed 64.64-bit fixed point number, !=0, EWMA of actual K. * @param _fL1 signed 64.64-bit fixed point number, >0, EWMA of actual L. * @param _mktVars contains 64.64 values for fIndexPriceS2*, fIndexPriceS3, fSigma2*, fSigma3, fRho23 * @param _fTargetDD signed 64.64-bit fixed point number * @return M1Star signed 64.64-bit fixed point number, >0 */ function getTargetCollateralM1( int128 _fK2, int128 _fL1, MarketVariables memory _mktVars, int128 _fTargetDD ) external pure virtual override returns (int128) { assert(_fK2 != 0); assert(_mktVars.fSigma3 == 0); assert(_mktVars.fIndexPriceS3 == 0); assert(_mktVars.fRho23 == 0); int128 fMu2 = HALF_64x64.neg().mul(_mktVars.fSigma2).mul(_mktVars.fSigma2); int128 ddScaled = _fK2 < 0 ? _mktVars.fSigma2.mul(_fTargetDD) : _mktVars.fSigma2.mul(_fTargetDD).neg(); int128 A1 = ABDKMath64x64.exp(fMu2.add(ddScaled)); return _fK2.mul(_mktVars.fIndexPriceS2).mul(A1).sub(_fL1); } /** * Calculate target collateral *M2* (Base Currency), when no M1, M3 is present * The targeted default probability is expressed using the inverse * _fTargetDD = Phi^(-1)(targetPD) * _fK2 in absolute terms must be 'reasonably large' * sigma3, rho23, IndexpriceS3 not relevant. * @param _fK2 signed 64.64-bit fixed point number, EWMA of actual K. * @param _fL1 signed 64.64-bit fixed point number, EWMA of actual L. * @param _mktVars contains 64.64 values for fIndexPriceS2, fIndexPriceS3, fSigma2, fSigma3, fRho23 * @param _fTargetDD signed 64.64-bit fixed point number * @return M2Star signed 64.64-bit fixed point number */ function getTargetCollateralM2( int128 _fK2, int128 _fL1, MarketVariables memory _mktVars, int128 _fTargetDD ) external pure virtual override returns (int128) { assert(_fK2 != 0); assert(_mktVars.fSigma3 == 0); assert(_mktVars.fIndexPriceS3 == 0); assert(_mktVars.fRho23 == 0); int128 fMu2 = HALF_64x64.mul(_mktVars.fSigma2).mul(_mktVars.fSigma2).neg(); int128 ddScaled = _fL1 < 0 ? _mktVars.fSigma2.mul(_fTargetDD) : _mktVars.fSigma2.mul(_fTargetDD).neg(); int128 A1 = ABDKMath64x64.exp(fMu2.add(ddScaled)).mul(_mktVars.fIndexPriceS2); return _fK2.sub(_fL1.div(A1)); } /** * Calculate target collateral M3 (Quanto Currency), when no M1, M2 not present * @param _fK2 signed 64.64-bit fixed point number. EWMA of actual K. * @param _fL1 signed 64.64-bit fixed point number. EWMA of actual L. * @param _mktVars contains 64.64 values for * fIndexPriceS2, fIndexPriceS3, fSigma2, fSigma3, fRho23 - all required * @param _fTargetDD signed 64.64-bit fixed point number * @return M2Star signed 64.64-bit fixed point number */ function getTargetCollateralM3( int128 _fK2, int128 _fL1, MarketVariables memory _mktVars, int128 _fTargetDD ) external pure override returns (int128) { assert(_fK2 != 0); assert(_mktVars.fSigma3 != 0); assert(_mktVars.fIndexPriceS3 != 0); assert(_mktVars.fRho23 != 0); // we solve the quadratic equation A x^2 + Bx + C = 0 // B = 2 * [X + Y * target_dd^2 * (exp(rho*sigma2*sigma3) - 1) ] // C = X^2 - Y^2 * target_dd^2 * (exp(sigma2^2) - 1) // where: // X = L1 / S3 - Y and Y = K2 * S2 / S3 // we re-use L1 for X and K2 for Y to save memory since they don't enter the equations otherwise _fK2 = _fK2.mul(_mktVars.fIndexPriceS2).div(_mktVars.fIndexPriceS3); // Y _fL1 = _fL1.div(_mktVars.fIndexPriceS3).sub(_fK2); // X // we only need the square of the target DD _fTargetDD = _fTargetDD.mul(_fTargetDD); // and we only need B/2 int128 fHalfB = _fL1.add( _fK2.mul(_fTargetDD.mul(_mktVars.fRho23.mul(_mktVars.fSigma2.mul(_mktVars.fSigma3)))) ); int128 fC = _fL1.mul(_fL1).sub( _fK2.mul(_fK2).mul(_fTargetDD).mul(_mktVars.fSigma2.mul(_mktVars.fSigma2)) ); // A = 1 - (exp(sigma3^2) - 1) * target_dd^2 int128 fA = ONE_64x64.sub(_mktVars.fSigma3.mul(_mktVars.fSigma3).mul(_fTargetDD)); // we re-use C to store the discriminant: D = (B/2)^2 - A * C fC = fHalfB.mul(fHalfB).sub(fA.mul(fC)); if (fC < 0) { // no solutions -> AMM is in profit, probability is smaller than target regardless of capital return int128(0); } // we want the larger of (-B/2 + sqrt((B/2)^2-A*C)) / A and (-B/2 - sqrt((B/2)^2-A*C)) / A // so it depends on the sign of A, or, equivalently, the sign of sqrt(...)/A fC = ABDKMath64x64.sqrt(fC).div(fA); fHalfB = fHalfB.div(fA); return fC > 0 ? fC.sub(fHalfB) : fC.neg().sub(fHalfB); } /** * Calculate the required deposit for a new position * of size _fPosition+_fTradeAmount and leverage _fTargetLeverage, * having an existing position with balance fBalance0 and size _fPosition. * This is the amount to be added to the margin collateral and can be negative (hence remove). * Fees not factored-in. * @param _fPosition0 signed 64.64-bit fixed point number. Position in base currency * @param _fBalance0 signed 64.64-bit fixed point number. Current balance. * @param _fTradeAmount signed 64.64-bit fixed point number. Trade amt in base currency * @param _fTargetLeverage signed 64.64-bit fixed point number. Desired leverage * @param _fPrice signed 64.64-bit fixed point number. Price for the trade of size _fTradeAmount * @param _fS2Mark signed 64.64-bit fixed point number. Mark-price * @param _fS3 signed 64.64-bit fixed point number. Collateral 2 quote conversion * @return signed 64.64-bit fixed point number. Required cash_cc */ function getDepositAmountForLvgPosition( int128 _fPosition0, int128 _fBalance0, int128 _fTradeAmount, int128 _fTargetLeverage, int128 _fPrice, int128 _fS2Mark, int128 _fS3, int128 _fS2 ) external pure override returns (int128) { // calculation has to be aligned with _getAvailableMargin and _executeTrade // calculation // otherwise the calculated deposit might not be enough to declare // the margin to be enough // aligned with get available margin balance int128 fPremiumCash = _fTradeAmount.mul(_fPrice.sub(_fS2)); int128 fDeltaLockedValue = _fTradeAmount.mul(_fS2); int128 fPnL = _fTradeAmount.mul(_fS2Mark); // we replace _fTradeAmount * price/S3 by // fDeltaLockedValue + fPremiumCash to be in line with // _executeTrade fPnL = fPnL.sub(fDeltaLockedValue).sub(fPremiumCash); int128 fLvgFrac = _fPosition0.add(_fTradeAmount).abs(); fLvgFrac = fLvgFrac.mul(_fS2Mark).div(_fTargetLeverage); fPnL = fPnL.sub(fLvgFrac).div(_fS3); _fBalance0 = _fBalance0.add(fPnL); return _fBalance0.neg(); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; import "../functions/AMMPerpLogic.sol"; interface IAMMPerpLogic { function volatilitySpread( uint16 _jumpTbps, uint16 _MinimalSpreadTbps, uint256 _numBlockSinceJump, int128 _fLambda ) external pure returns (int128); function holdingPeriodPenalty(uint256 _numBlockSinceLastOpen, int128 _fLambda) external pure returns (uint16); function calculateDefaultFundSize( int128[2] memory _fK2AMM, int128 _fk2Trader, int128 _fCoverN, int128[2] memory fStressRet2, int128[2] memory fStressRet3, int128[2] memory fIndexPrices, AMMPerpLogic.CollateralCurrency _eCCY ) external pure returns (int128); function calculateRiskNeutralPD( AMMPerpLogic.AMMVariables memory _ammVars, AMMPerpLogic.MarketVariables memory _mktVars, int128 _fTradeAmount, bool _withCDF ) external view returns (int128, int128); function calculatePerpetualPrice( AMMPerpLogic.AMMVariables memory _ammVars, AMMPerpLogic.MarketVariables memory _mktVars, int128 _fTradeAmount, int128 _fBidAskSpread, int128 _fIncentiveSpread ) external view returns (int128); function getTargetCollateralM1( int128 _fK2, int128 _fL1, AMMPerpLogic.MarketVariables memory _mktVars, int128 _fTargetDD ) external pure returns (int128); function getTargetCollateralM2( int128 _fK2, int128 _fL1, AMMPerpLogic.MarketVariables memory _mktVars, int128 _fTargetDD ) external pure returns (int128); function getTargetCollateralM3( int128 _fK2, int128 _fL1, AMMPerpLogic.MarketVariables memory _mktVars, int128 _fTargetDD ) external pure returns (int128); function getDepositAmountForLvgPosition( int128 _fPosition0, int128 _fBalance0, int128 _fTradeAmount, int128 _fTargetLeverage, int128 _fPrice, int128 _fS2Mark, int128 _fS3, int128 _fS2 ) external pure returns (int128); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; interface IFunctionList { function getFunctionList() external pure returns (bytes4[] memory functionSignatures, bytes32 moduleName); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; import "./IPerpetualOrder.sol"; /** * @notice The libraryEvents defines events that will be raised from modules (contract/modules). * @dev DO REMEMBER to add new events in modules here. */ interface ILibraryEvents { // PerpetualModule event Clear(uint24 indexed perpetualId, address indexed trader); event Settle(uint24 indexed perpetualId, address indexed trader, int256 amount); event SettlementComplete(uint24 indexed perpetualId); event SetNormalState(uint24 indexed perpetualId); event SetEmergencyState( uint24 indexed perpetualId, int128 fSettlementMarkPremiumRate, int128 fSettlementS2Price, int128 fSettlementS3Price ); event SettleState(uint24 indexed perpetualId); event SetClearedState(uint24 indexed perpetualId); event UpdateUnitAccumulatedFunding(uint24 perpetualId, int128 unitAccumulativeFunding); // Participation pool event LiquidityAdded( uint8 indexed poolId, address indexed user, uint256 tokenAmount, uint256 shareAmount ); event LiquidityProvisionPaused(bool pauseOn, uint8 poolId); event LiquidityRemoved( uint8 indexed poolId, address indexed user, uint256 tokenAmount, uint256 shareAmount ); event LiquidityWithdrawalInitiated( uint8 indexed poolId, address indexed user, uint256 shareAmount ); // setters // oracles event SetOracles(uint24 indexed perpetualId, bytes4[2] baseQuoteS2, bytes4[2] baseQuoteS3); // perp parameters event SetPerpetualBaseParameters(uint24 indexed perpetualId, int128[7] baseParams); event SetPerpetualRiskParameters( uint24 indexed perpetualId, int128[5] underlyingRiskParams, int128[12] defaultFundRiskParams ); event SetParameter(uint24 indexed perpetualId, string name, int128 value); event SetParameterPair(uint24 indexed perpetualId, string name, int128 value1, int128 value2); // pool parameters event SetPoolParameter(uint8 indexed poolId, string name, int128 value); event TransferAddressTo(string name, address oldOBFactory, address newOBFactory); // only governance event SetBlockDelay(uint8 delay); // fee structure parameters event SetBrokerDesignations(uint32[] designations, uint16[] fees); event SetBrokerTiers(uint256[] tiers, uint16[] feesTbps); event SetTraderTiers(uint256[] tiers, uint16[] feesTbps); event SetTraderVolumeTiers(uint256[] tiers, uint16[] feesTbps); event SetBrokerVolumeTiers(uint256[] tiers, uint16[] feesTbps); event SetUtilityToken(address tokenAddr); event BrokerLotsTransferred( uint8 indexed poolId, address oldOwner, address newOwner, uint32 numLots ); event BrokerVolumeTransferred( uint8 indexed poolId, address oldOwner, address newOwner, int128 fVolume ); // funds event UpdateParticipationFundCash( uint8 indexed poolId, int128 fDeltaAmountCC, int128 fNewFundCash ); event UpdateDefaultFundCash(uint8 indexed poolId, int128 fDeltaAmountCC, int128 fNewFundCash); // brokers event UpdateBrokerAddedCash(uint8 indexed poolId, uint32 iLots, uint32 iNewBrokerLots); event UpdateBrokerFundCash(uint8 indexed poolId, int128 fDeltaAmountCC, int128 fNewFundCash); // TradeModule event Trade( uint24 indexed perpetualId, address indexed trader, bytes16 indexed positionId, IPerpetualOrder.Order order, bytes32 orderDigest, int128 newPositionSizeBC, int128 price, int128 fFeeCC, int128 fPnlCC, int128 fB2C ); event UpdateMarginAccount( uint24 indexed perpetualId, address indexed trader, bytes16 indexed positionId, int128 fPositionBC, int128 fCashCC, int128 fLockedInValueQC, int128 fFundingPaymentCC, int128 fOpenInterestBC ); event Liquidate( uint24 perpetualId, address indexed liquidator, address indexed trader, bytes16 indexed positionId, int128 amountLiquidatedBC, int128 liquidationPrice, int128 newPositionSizeBC, int128 fFeeCC, int128 fPnlCC ); event TransferFeeToexecutor( uint24 indexed perpetualId, address indexed trader, address indexed executor, int128 referralRebate ); event TransferFeeToBroker(uint24 indexed perpetualId, address indexed broker, int128 feeCC); event PerpetualLimitOrderCancelled(uint24 indexed perpetualId, bytes32 indexed orderHash); event DistributeFees( uint8 indexed poolId, uint24 indexed perpetualId, address indexed trader, int128 protocolFeeCC, int128 participationFundFeeCC ); // PerpetualManager/factory event RunLiquidityPool(uint8 _liqPoolID); event LiquidityPoolCreated( uint8 id, address marginTokenAddress, address shareTokenAddress, uint16 iTargetPoolSizeUpdateTime, int128 fBrokerCollateralLotSize ); event PerpetualCreated( uint8 poolId, uint24 id, int128[7] baseParams, int128[5] underlyingRiskParams, int128[12] defaultFundRiskParams, uint256 eCollateralCurrency ); // emit tokenAddr==0x0 if the token paid is the aggregated token, otherwise the address of the token event TokensDeposited(uint24 indexed perpetualId, address indexed trader, int128 amount); event TokensWithdrawn(uint24 indexed perpetualId, address indexed trader, int128 amount); event UpdateMarkPrice( uint24 indexed perpetualId, int128 fMidPricePremium, int128 fMarkPricePremium, int128 fSpotIndexPrice ); event UpdateFundingRate(uint24 indexed perpetualId, int128 fFundingRate); event UpdateAMMFundTargetSize( uint24 indexed perpetualId, uint8 indexed liquidityPoolId, int128 fTargetAMMFundSizeInPerpetual, int128 fTargetAMMFundSizeInPool ); event UpdateDefaultFundTargetSize( uint8 indexed liquidityPoolId, int128 fDefaultFundCashCC, int128 fTargetDFSize ); event UpdateReprTradeSizes( uint24 indexed perpetualId, int128 fCurrentTraderExposureEMA, int128 fCurrentAMMExposureEMAShort, int128 fCurrentAMMExposureEMALong ); event TransferEarningsToTreasury(uint8 _poolId, int128 fEarnings, int128 newDefaultFundSize); event SetDelegate(address trader, address delegate); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; interface IPerpetualOrder { struct Order { uint16 leverageTDR; // 12.43x leverage is represented by 1243 (two-digit integer representation); 0 if deposit and trade separate uint16 brokerFeeTbps; // broker can set their own fee uint24 iPerpetualId; // global id for perpetual address traderAddr; // address of trader uint32 executionTimestamp; // normally set to current timestamp; order will not be executed prior to this timestamp. address brokerAddr; // address of the broker or zero uint32 submittedTimestamp; uint32 flags; // order flags uint32 iDeadline; //deadline for price (seconds timestamp) address executorAddr; // address of the executor set by contract int128 fAmount; // amount in base currency to be traded int128 fLimitPrice; // limit price int128 fTriggerPrice; //trigger price. Non-zero for stop orders. bytes brokerSignature; //signature of broker (or 0) } }
{ "optimizer": { "enabled": true, "runs": 400 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"},{"indexed":false,"internalType":"uint32","name":"numLots","type":"uint32"}],"name":"BrokerLotsTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"},{"indexed":false,"internalType":"int128","name":"fVolume","type":"int128"}],"name":"BrokerVolumeTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"address","name":"trader","type":"address"}],"name":"Clear","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"int128","name":"protocolFeeCC","type":"int128"},{"indexed":false,"internalType":"int128","name":"participationFundFeeCC","type":"int128"}],"name":"DistributeFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernance","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernance","type":"address"}],"name":"GovernanceTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"_sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"_oldImplementation","type":"address"},{"indexed":true,"internalType":"address","name":"_newImplementation","type":"address"}],"name":"ImplementationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"bytes16","name":"positionId","type":"bytes16"},{"indexed":false,"internalType":"int128","name":"amountLiquidatedBC","type":"int128"},{"indexed":false,"internalType":"int128","name":"liquidationPrice","type":"int128"},{"indexed":false,"internalType":"int128","name":"newPositionSizeBC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fFeeCC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fPnlCC","type":"int128"}],"name":"Liquidate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"LiquidityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"id","type":"uint8"},{"indexed":false,"internalType":"address","name":"marginTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"shareTokenAddress","type":"address"},{"indexed":false,"internalType":"uint16","name":"iTargetPoolSizeUpdateTime","type":"uint16"},{"indexed":false,"internalType":"int128","name":"fBrokerCollateralLotSize","type":"int128"}],"name":"LiquidityPoolCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"pauseOn","type":"bool"},{"indexed":false,"internalType":"uint8","name":"poolId","type":"uint8"}],"name":"LiquidityProvisionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"LiquidityRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"LiquidityWithdrawalInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousMaintainer","type":"address"},{"indexed":true,"internalType":"address","name":"newMaintainer","type":"address"}],"name":"MaintainerTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":false,"internalType":"uint24","name":"id","type":"uint24"},{"indexed":false,"internalType":"int128[7]","name":"baseParams","type":"int128[7]"},{"indexed":false,"internalType":"int128[5]","name":"underlyingRiskParams","type":"int128[5]"},{"indexed":false,"internalType":"int128[12]","name":"defaultFundRiskParams","type":"int128[12]"},{"indexed":false,"internalType":"uint256","name":"eCollateralCurrency","type":"uint256"}],"name":"PerpetualCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"PerpetualLimitOrderCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"_newOwner","type":"address"}],"name":"ProxyOwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"_liqPoolID","type":"uint8"}],"name":"RunLiquidityPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"delay","type":"uint8"}],"name":"SetBlockDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32[]","name":"designations","type":"uint32[]"},{"indexed":false,"internalType":"uint16[]","name":"fees","type":"uint16[]"}],"name":"SetBrokerDesignations","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"tiers","type":"uint256[]"},{"indexed":false,"internalType":"uint16[]","name":"feesTbps","type":"uint16[]"}],"name":"SetBrokerTiers","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"tiers","type":"uint256[]"},{"indexed":false,"internalType":"uint16[]","name":"feesTbps","type":"uint16[]"}],"name":"SetBrokerVolumeTiers","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"}],"name":"SetClearedState","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"address","name":"delegate","type":"address"}],"name":"SetDelegate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":false,"internalType":"int128","name":"fSettlementMarkPremiumRate","type":"int128"},{"indexed":false,"internalType":"int128","name":"fSettlementS2Price","type":"int128"},{"indexed":false,"internalType":"int128","name":"fSettlementS3Price","type":"int128"}],"name":"SetEmergencyState","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"}],"name":"SetNormalState","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":false,"internalType":"bytes4[2]","name":"baseQuoteS2","type":"bytes4[2]"},{"indexed":false,"internalType":"bytes4[2]","name":"baseQuoteS3","type":"bytes4[2]"}],"name":"SetOracles","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"int128","name":"value","type":"int128"}],"name":"SetParameter","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"int128","name":"value1","type":"int128"},{"indexed":false,"internalType":"int128","name":"value2","type":"int128"}],"name":"SetParameterPair","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":false,"internalType":"int128[7]","name":"baseParams","type":"int128[7]"}],"name":"SetPerpetualBaseParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":false,"internalType":"int128[5]","name":"underlyingRiskParams","type":"int128[5]"},{"indexed":false,"internalType":"int128[12]","name":"defaultFundRiskParams","type":"int128[12]"}],"name":"SetPerpetualRiskParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"int128","name":"value","type":"int128"}],"name":"SetPoolParameter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"tiers","type":"uint256[]"},{"indexed":false,"internalType":"uint16[]","name":"feesTbps","type":"uint16[]"}],"name":"SetTraderTiers","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"tiers","type":"uint256[]"},{"indexed":false,"internalType":"uint16[]","name":"feesTbps","type":"uint16[]"}],"name":"SetTraderVolumeTiers","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenAddr","type":"address"}],"name":"SetUtilityToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"int256","name":"amount","type":"int256"}],"name":"Settle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"}],"name":"SettleState","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"}],"name":"SettlementComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"int128","name":"amount","type":"int128"}],"name":"TokensDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"int128","name":"amount","type":"int128"}],"name":"TokensWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"bytes16","name":"positionId","type":"bytes16"},{"components":[{"internalType":"uint16","name":"leverageTDR","type":"uint16"},{"internalType":"uint16","name":"brokerFeeTbps","type":"uint16"},{"internalType":"uint24","name":"iPerpetualId","type":"uint24"},{"internalType":"address","name":"traderAddr","type":"address"},{"internalType":"uint32","name":"executionTimestamp","type":"uint32"},{"internalType":"address","name":"brokerAddr","type":"address"},{"internalType":"uint32","name":"submittedTimestamp","type":"uint32"},{"internalType":"uint32","name":"flags","type":"uint32"},{"internalType":"uint32","name":"iDeadline","type":"uint32"},{"internalType":"address","name":"executorAddr","type":"address"},{"internalType":"int128","name":"fAmount","type":"int128"},{"internalType":"int128","name":"fLimitPrice","type":"int128"},{"internalType":"int128","name":"fTriggerPrice","type":"int128"},{"internalType":"bytes","name":"brokerSignature","type":"bytes"}],"indexed":false,"internalType":"struct IPerpetualOrder.Order","name":"order","type":"tuple"},{"indexed":false,"internalType":"bytes32","name":"orderDigest","type":"bytes32"},{"indexed":false,"internalType":"int128","name":"newPositionSizeBC","type":"int128"},{"indexed":false,"internalType":"int128","name":"price","type":"int128"},{"indexed":false,"internalType":"int128","name":"fFeeCC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fPnlCC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fB2C","type":"int128"}],"name":"Trade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"address","name":"oldOBFactory","type":"address"},{"indexed":false,"internalType":"address","name":"newOBFactory","type":"address"}],"name":"TransferAddressTo","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"_poolId","type":"uint8"},{"indexed":false,"internalType":"int128","name":"fEarnings","type":"int128"},{"indexed":false,"internalType":"int128","name":"newDefaultFundSize","type":"int128"}],"name":"TransferEarningsToTreasury","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"address","name":"broker","type":"address"},{"indexed":false,"internalType":"int128","name":"feeCC","type":"int128"}],"name":"TransferFeeToBroker","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"address","name":"executor","type":"address"},{"indexed":false,"internalType":"int128","name":"referralRebate","type":"int128"}],"name":"TransferFeeToexecutor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"uint8","name":"liquidityPoolId","type":"uint8"},{"indexed":false,"internalType":"int128","name":"fTargetAMMFundSizeInPerpetual","type":"int128"},{"indexed":false,"internalType":"int128","name":"fTargetAMMFundSizeInPool","type":"int128"}],"name":"UpdateAMMFundTargetSize","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"iLots","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"iNewBrokerLots","type":"uint32"}],"name":"UpdateBrokerAddedCash","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":false,"internalType":"int128","name":"fDeltaAmountCC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fNewFundCash","type":"int128"}],"name":"UpdateBrokerFundCash","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":false,"internalType":"int128","name":"fDeltaAmountCC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fNewFundCash","type":"int128"}],"name":"UpdateDefaultFundCash","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"liquidityPoolId","type":"uint8"},{"indexed":false,"internalType":"int128","name":"fDefaultFundCashCC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fTargetDFSize","type":"int128"}],"name":"UpdateDefaultFundTargetSize","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":false,"internalType":"int128","name":"fFundingRate","type":"int128"}],"name":"UpdateFundingRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"bytes16","name":"positionId","type":"bytes16"},{"indexed":false,"internalType":"int128","name":"fPositionBC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fCashCC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fLockedInValueQC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fFundingPaymentCC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fOpenInterestBC","type":"int128"}],"name":"UpdateMarginAccount","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":false,"internalType":"int128","name":"fMidPricePremium","type":"int128"},{"indexed":false,"internalType":"int128","name":"fMarkPricePremium","type":"int128"},{"indexed":false,"internalType":"int128","name":"fSpotIndexPrice","type":"int128"}],"name":"UpdateMarkPrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"poolId","type":"uint8"},{"indexed":false,"internalType":"int128","name":"fDeltaAmountCC","type":"int128"},{"indexed":false,"internalType":"int128","name":"fNewFundCash","type":"int128"}],"name":"UpdateParticipationFundCash","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":false,"internalType":"int128","name":"fCurrentTraderExposureEMA","type":"int128"},{"indexed":false,"internalType":"int128","name":"fCurrentAMMExposureEMAShort","type":"int128"},{"indexed":false,"internalType":"int128","name":"fCurrentAMMExposureEMALong","type":"int128"}],"name":"UpdateReprTradeSizes","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint24","name":"perpetualId","type":"uint24"},{"indexed":false,"internalType":"int128","name":"unitAccumulativeFunding","type":"int128"}],"name":"UpdateUnitAccumulatedFunding","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"bytes4","name":"_sig","type":"bytes4"}],"name":"getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_moduleName","type":"string"}],"name":"getModuleImplementationAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProxyOwner","outputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maintainer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_impl","type":"address"}],"name":"setImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_impl","type":"address"}],"name":"setImplementationCrossModules","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setProxyOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGovernance","type":"address"}],"name":"transferGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMaintainer","type":"address"}],"name":"transferMaintainer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801562000010575f80fd5b506200001c3362000048565b620000273362000097565b6001805460ff60a01b191681556002556200004233620000e8565b620001ab565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f2f3ffaaaad93928855c8700645d1a3643e6ccfdd500efa9fda048a88f557cf019190a35050565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce80905f90a35050565b6001600160a01b038116620001435760405162461bcd60e51b815260206004820152601b60248201527f696e76616c69642070726f7879206f776e657220616464726573730000000000604482015260640160405180910390fd5b6001600160a01b038116620001645f80516020620018db8339815191525490565b6001600160a01b03167f5a3e66efaa1e445ebd894728a69d6959842ea1e97bd79b892797106e270efcd960405160405180910390a35f80516020620018db83398151915255565b61172280620001b95f395ff3fe6080604052600436106100d4575f3560e01c80638456cb591161007e578063caaee91c11610058578063caaee91c1461020f578063d38bfff41461022e578063d784d4261461024d578063dc9cc6451461026c576100e3565b80638456cb59146101c05780639850d32b146101d4578063bffd952a146101f0576100e3565b80633f4ba83a116100af5780633f4ba83a146101665780635aa6e6751461017a5780635c975abb14610197576100e3565b806233c04b146100eb5780630e1cf91b146101275780631ab7710d14610146576100e3565b366100e3576100e161028b565b005b6100e161028b565b3480156100f6575f80fd5b5061010a6101053660046114a9565b61029d565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610132575f80fd5b506100e1610141366004611515565b610301565b348015610151575f80fd5b505f805160206116cd8339815191525461010a565b348015610171575f80fd5b506100e1610379565b348015610185575f80fd5b506001546001600160a01b031661010a565b3480156101a2575f80fd5b50600154600160a01b900460ff16604051901515815260200161011e565b3480156101cb575f80fd5b506100e161042b565b3480156101df575f80fd5b505f546001600160a01b031661010a565b3480156101fb575f80fd5b506100e161020a366004611515565b6104da565b34801561021a575f80fd5b506100e1610229366004611515565b610574565b348015610239575f80fd5b506100e1610248366004611515565b6105e2565b348015610258575f80fd5b506100e1610267366004611515565b61067c565b348015610277575f80fd5b5061010a610286366004611550565b6106eb565b61029b6102966106f5565b610768565b565b5f60125f6102df85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061078692505050565b815260208101919091526040015f20546001600160a01b031690505b92915050565b5f805160206116cd833981519152546001600160a01b0316336001600160a01b03161461036b5760405162461bcd60e51b8152602060048201526013602482015272141c9bde1e4e9858d8d95cdcc819195b9a5959606a1b60448201526064015b60405180910390fd5b6103768160016107a3565b50565b600154600160a01b900460ff166103c95760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610362565b336103db5f546001600160a01b031690565b6001600160a01b0316146104235760405162461bcd60e51b815260206004820152600f60248201526e37b7363c9036b0b4b73a30b4b732b960891b6044820152606401610362565b61029b610aff565b600154600160a01b900460ff16156104785760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610362565b3361048a5f546001600160a01b031690565b6001600160a01b0316146104d25760405162461bcd60e51b815260206004820152600f60248201526e37b7363c9036b0b4b73a30b4b732b960891b6044820152606401610362565b61029b610b9c565b6001546001600160a01b031633146105265760405162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b6044820152606401610362565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152600c60248201526b7a65726f206164647265737360a01b6044820152606401610362565b61037681610c24565b5f805160206116cd833981519152546001600160a01b0316336001600160a01b0316146105d95760405162461bcd60e51b8152602060048201526013602482015272141c9bde1e4e9858d8d95cdcc819195b9a5959606a1b6044820152606401610362565b61037681610c73565b6001546001600160a01b0316331461062e5760405162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b6044820152606401610362565b6001600160a01b0381166106735760405162461bcd60e51b815260206004820152600c60248201526b7a65726f206164647265737360a01b6044820152606401610362565b61037681610d2e565b5f805160206116cd833981519152546001600160a01b0316336001600160a01b0316146106e15760405162461bcd60e51b8152602060048201526013602482015272141c9bde1e4e9858d8d95cdcc819195b9a5959606a1b6044820152606401610362565b610376815f6107a3565b5f6102fb82610d7f565b5f8061070b5f356001600160e01b031916610d7f565b90506001600160a01b0381166107635760405162461bcd60e51b815260206004820152601e60248201527f50726f78793a496d706c656d656e746174696f6e206e6f7420666f756e6400006044820152606401610362565b919050565b365f80375f80365f845af43d5f803e808015610782573d5ff35b3d5ffd5b80515f908290820361079a57505f92915050565b50506020015190565b6001600160a01b0382166107f95760405162461bcd60e51b815260206004820152601e60248201527f696e76616c696420696d706c656d656e746174696f6e206164647265737300006044820152606401610362565b5f80836001600160a01b0316633e6b8c0d6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610836573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261085d919081019061158a565b9092509050806108af5760405162461bcd60e51b815260206004820152601b60248201527f4d6f64756c65206e616d652063616e6e6f7420626520656d70747900000000006044820152606401610362565b5f81815260116020526040812090806108c9836001015490565b8551911091505f5b81811015610a23575f8682815181106108ec576108ec611652565b6020026020010151905061092287838151811061090b5761090b611652565b602002602001015186610dd890919063ffffffff16565b6109ed575f61093082610d7f565b90506001600160a01b038116156109be578861098e5760405162461bcd60e51b815260206004820152601a60248201527f63616e74207265706c616365206d6f64756c65732066756e63730000000000006044820152606401610362565b6001600160a01b0381165f908152601360209081526040808320548352601190915290206109bc9083610df6565b505b6109ea8884815181106109d3576109d3611652565b602002602001015187610f6790919063ffffffff16565b50505b610a10878381518110610a0257610a02611652565b60200260200101518a610fe5565b5080610a1b8161167a565b9150506108d1565b508115610abc575f610a425f610a3a866001015490565b8691906110a6565b9050805191505f5b82811015610ab9575f828281518110610a6557610a65611652565b60200260200101519050896001600160a01b0316610a8282610d7f565b6001600160a01b031614610aa657610a9a815f610fe5565b610aa48682610df6565b505b5080610ab18161167a565b915050610a4a565b50505b5050505f81815260126020908152604080832080546001600160a01b039098166001600160a01b0319909816881790559582526013905293909320929092555050565b600154600160a01b900460ff16610b4f5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610362565b6001805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600154600160a01b900460ff1615610be95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610362565b6001805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610b7f3390565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f2f3ffaaaad93928855c8700645d1a3643e6ccfdd500efa9fda048a88f557cf019190a35050565b6001600160a01b038116610cc95760405162461bcd60e51b815260206004820152601b60248201527f696e76616c69642070726f7879206f776e6572206164647265737300000000006044820152606401610362565b806001600160a01b0316610ce85f805160206116cd8339815191525490565b6001600160a01b03167f5a3e66efaa1e445ebd894728a69d6959842ea1e97bd79b892797106e270efcd960405160405180910390a35f805160206116cd83398151915255565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce80905f90a35050565b604080516001600160e01b0319929092166020808401919091527f950d7e977b74051843ed988c77d53a700cd967d2ac5480d98dd4c1edaf0b4dc883830152815180840383018152606090930190915281519101205490565b6001600160e01b0319165f9081526020919091526040902054151590565b6001600160e01b031981165f9081526020839052604081205415610f60576001600160e01b031982165f90815260208490526040812054610e3990600190611692565b6001858101549192505f91610e4e9190611692565b9050818114610efc575f856001018281548110610e6d57610e6d611652565b905f5260205f2090600891828204019190066004029054906101000a900460e01b905080866001018481548110610ea657610ea6611652565b905f5260205f2090600891828204019190066004026101000a81548163ffffffff021916908360e01c0217905550826001610ee191906116a5565b6001600160e01b03199091165f908152602087905260409020555b6001600160e01b031984165f9081526020869052604081205560018501805480610f2857610f286116b8565b5f8281526020902060085f1990920191820401805463ffffffff600460078516026101000a0219169055905550600191506102fb9050565b505f6102fb565b6001600160e01b031981165f90815260208390526040812054610f6057506001828101805480830182555f82815260208082206008840401805463ffffffff60079095166004026101000a948502191660e088901c949094029390931790925591546001600160e01b031985168352908590526040909120556102fb565b610fee8261121d565b806001600160a01b031661100183610d7f565b6040516001600160e01b0319851681526001600160a01b0391909116907f347b48699b991c95bb339a3a778222488794b19790e9f46171825933c63a9cc49060200160405180910390a3604080516001600160e01b0319939093166020808501919091527f950d7e977b74051843ed988c77d53a700cd967d2ac5480d98dd4c1edaf0b4dc8848301528151808503830181526060909401909152825192019190912055565b60605f6110b383856116a5565b9050838110156111055760405162461bcd60e51b815260206004820152601160248201527f6164646974696f6e206f766572666c6f770000000000000000000000000000006044820152606401610362565b60018501548111611116578061111c565b60018501545b905080158061112b5750808410155b156111365750611216565b6111408482611692565b67ffffffffffffffff8111156111585761115861156b565b604051908082528060200260200182016040528015611181578160200160208202803683370190505b5091505f5b6111908583611692565b81101561121357600186016111a586836116a5565b815481106111b5576111b5611652565b905f5260205f2090600891828204019190066004029054906101000a900460e01b8382815181106111e8576111e8611652565b6001600160e01b0319909216602092830291909101909101528061120b8161167a565b915050611186565b50505b9392505050565b5f6112266112c9565b80519091505f5b818110156112c35782818151811061124757611247611652565b60200260200101516001600160e01b031916846001600160e01b031916036112b15760405162461bcd60e51b815260206004820152601a60248201527f66756e6374696f6e20696420616c7265616479206578697374730000000000006044820152606401610362565b806112bb8161167a565b91505061122d565b50505050565b60408051600880825261012082019092526060915f9190602082016101008036833701905050905063dc9cc64560e01b815f8151811061130b5761130b611652565b6001600160e01b0319909216602092830291909101909101528051636bc26a1360e11b908290600190811061134257611342611652565b6001600160e01b0319909216602092830291909101909101528051630e1cf91b60e01b908290600290811061137957611379611652565b6001600160e01b03199092166020928302919091019091015280516233c04b60e01b90829060039081106113af576113af611652565b6001600160e01b03199092166020928302919091019091015280516332abba4760e21b90829060049081106113e6576113e6611652565b6001600160e01b0319909216602092830291909101909101528051631ab7710d60e01b908290600590811061141d5761141d611652565b6001600160e01b0319909216602092830291909101909101528051638456cb5960e01b908290600690811061145457611454611652565b6001600160e01b0319909216602092830291909101909101528051631fa5d41d60e11b908290600790811061148b5761148b611652565b6001600160e01b031990921660209283029190910190910152919050565b5f80602083850312156114ba575f80fd5b823567ffffffffffffffff808211156114d1575f80fd5b818501915085601f8301126114e4575f80fd5b8135818111156114f2575f80fd5b866020828501011115611503575f80fd5b60209290920196919550909350505050565b5f60208284031215611525575f80fd5b81356001600160a01b0381168114611216575f80fd5b6001600160e01b031981168114610376575f80fd5b5f60208284031215611560575f80fd5b81356112168161153b565b634e487b7160e01b5f52604160045260245ffd5b80516107638161153b565b5f806040838503121561159b575f80fd5b825167ffffffffffffffff808211156115b2575f80fd5b818501915085601f8301126115c5575f80fd5b81516020828211156115d9576115d961156b565b8160051b604051601f19603f830116810181811086821117156115fe576115fe61156b565b60405292835281830193508481018201928984111561161b575f80fd5b948201945b83861015611640576116318661157f565b85529482019493820193611620565b97909101519698969750505050505050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f6001820161168b5761168b611666565b5060010190565b818103818111156102fb576102fb611666565b808201808211156102fb576102fb611666565b634e487b7160e01b5f52603160045260245ffdfeb5f6074d2b374487ffe12d401cf0891c7591a84c4944ef117f69d13b80c4d6d8a264697066735822122090e7122bc8d3ea42235cdf8d59d4687ca19d2c41d243027e640f1c695b907a2664736f6c63430008150033b5f6074d2b374487ffe12d401cf0891c7591a84c4944ef117f69d13b80c4d6d8
Deployed Bytecode
0x6080604052600436106100d4575f3560e01c80638456cb591161007e578063caaee91c11610058578063caaee91c1461020f578063d38bfff41461022e578063d784d4261461024d578063dc9cc6451461026c576100e3565b80638456cb59146101c05780639850d32b146101d4578063bffd952a146101f0576100e3565b80633f4ba83a116100af5780633f4ba83a146101665780635aa6e6751461017a5780635c975abb14610197576100e3565b806233c04b146100eb5780630e1cf91b146101275780631ab7710d14610146576100e3565b366100e3576100e161028b565b005b6100e161028b565b3480156100f6575f80fd5b5061010a6101053660046114a9565b61029d565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610132575f80fd5b506100e1610141366004611515565b610301565b348015610151575f80fd5b505f805160206116cd8339815191525461010a565b348015610171575f80fd5b506100e1610379565b348015610185575f80fd5b506001546001600160a01b031661010a565b3480156101a2575f80fd5b50600154600160a01b900460ff16604051901515815260200161011e565b3480156101cb575f80fd5b506100e161042b565b3480156101df575f80fd5b505f546001600160a01b031661010a565b3480156101fb575f80fd5b506100e161020a366004611515565b6104da565b34801561021a575f80fd5b506100e1610229366004611515565b610574565b348015610239575f80fd5b506100e1610248366004611515565b6105e2565b348015610258575f80fd5b506100e1610267366004611515565b61067c565b348015610277575f80fd5b5061010a610286366004611550565b6106eb565b61029b6102966106f5565b610768565b565b5f60125f6102df85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061078692505050565b815260208101919091526040015f20546001600160a01b031690505b92915050565b5f805160206116cd833981519152546001600160a01b0316336001600160a01b03161461036b5760405162461bcd60e51b8152602060048201526013602482015272141c9bde1e4e9858d8d95cdcc819195b9a5959606a1b60448201526064015b60405180910390fd5b6103768160016107a3565b50565b600154600160a01b900460ff166103c95760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610362565b336103db5f546001600160a01b031690565b6001600160a01b0316146104235760405162461bcd60e51b815260206004820152600f60248201526e37b7363c9036b0b4b73a30b4b732b960891b6044820152606401610362565b61029b610aff565b600154600160a01b900460ff16156104785760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610362565b3361048a5f546001600160a01b031690565b6001600160a01b0316146104d25760405162461bcd60e51b815260206004820152600f60248201526e37b7363c9036b0b4b73a30b4b732b960891b6044820152606401610362565b61029b610b9c565b6001546001600160a01b031633146105265760405162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b6044820152606401610362565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152600c60248201526b7a65726f206164647265737360a01b6044820152606401610362565b61037681610c24565b5f805160206116cd833981519152546001600160a01b0316336001600160a01b0316146105d95760405162461bcd60e51b8152602060048201526013602482015272141c9bde1e4e9858d8d95cdcc819195b9a5959606a1b6044820152606401610362565b61037681610c73565b6001546001600160a01b0316331461062e5760405162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b6044820152606401610362565b6001600160a01b0381166106735760405162461bcd60e51b815260206004820152600c60248201526b7a65726f206164647265737360a01b6044820152606401610362565b61037681610d2e565b5f805160206116cd833981519152546001600160a01b0316336001600160a01b0316146106e15760405162461bcd60e51b8152602060048201526013602482015272141c9bde1e4e9858d8d95cdcc819195b9a5959606a1b6044820152606401610362565b610376815f6107a3565b5f6102fb82610d7f565b5f8061070b5f356001600160e01b031916610d7f565b90506001600160a01b0381166107635760405162461bcd60e51b815260206004820152601e60248201527f50726f78793a496d706c656d656e746174696f6e206e6f7420666f756e6400006044820152606401610362565b919050565b365f80375f80365f845af43d5f803e808015610782573d5ff35b3d5ffd5b80515f908290820361079a57505f92915050565b50506020015190565b6001600160a01b0382166107f95760405162461bcd60e51b815260206004820152601e60248201527f696e76616c696420696d706c656d656e746174696f6e206164647265737300006044820152606401610362565b5f80836001600160a01b0316633e6b8c0d6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610836573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261085d919081019061158a565b9092509050806108af5760405162461bcd60e51b815260206004820152601b60248201527f4d6f64756c65206e616d652063616e6e6f7420626520656d70747900000000006044820152606401610362565b5f81815260116020526040812090806108c9836001015490565b8551911091505f5b81811015610a23575f8682815181106108ec576108ec611652565b6020026020010151905061092287838151811061090b5761090b611652565b602002602001015186610dd890919063ffffffff16565b6109ed575f61093082610d7f565b90506001600160a01b038116156109be578861098e5760405162461bcd60e51b815260206004820152601a60248201527f63616e74207265706c616365206d6f64756c65732066756e63730000000000006044820152606401610362565b6001600160a01b0381165f908152601360209081526040808320548352601190915290206109bc9083610df6565b505b6109ea8884815181106109d3576109d3611652565b602002602001015187610f6790919063ffffffff16565b50505b610a10878381518110610a0257610a02611652565b60200260200101518a610fe5565b5080610a1b8161167a565b9150506108d1565b508115610abc575f610a425f610a3a866001015490565b8691906110a6565b9050805191505f5b82811015610ab9575f828281518110610a6557610a65611652565b60200260200101519050896001600160a01b0316610a8282610d7f565b6001600160a01b031614610aa657610a9a815f610fe5565b610aa48682610df6565b505b5080610ab18161167a565b915050610a4a565b50505b5050505f81815260126020908152604080832080546001600160a01b039098166001600160a01b0319909816881790559582526013905293909320929092555050565b600154600160a01b900460ff16610b4f5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610362565b6001805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600154600160a01b900460ff1615610be95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610362565b6001805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610b7f3390565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f2f3ffaaaad93928855c8700645d1a3643e6ccfdd500efa9fda048a88f557cf019190a35050565b6001600160a01b038116610cc95760405162461bcd60e51b815260206004820152601b60248201527f696e76616c69642070726f7879206f776e6572206164647265737300000000006044820152606401610362565b806001600160a01b0316610ce85f805160206116cd8339815191525490565b6001600160a01b03167f5a3e66efaa1e445ebd894728a69d6959842ea1e97bd79b892797106e270efcd960405160405180910390a35f805160206116cd83398151915255565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce80905f90a35050565b604080516001600160e01b0319929092166020808401919091527f950d7e977b74051843ed988c77d53a700cd967d2ac5480d98dd4c1edaf0b4dc883830152815180840383018152606090930190915281519101205490565b6001600160e01b0319165f9081526020919091526040902054151590565b6001600160e01b031981165f9081526020839052604081205415610f60576001600160e01b031982165f90815260208490526040812054610e3990600190611692565b6001858101549192505f91610e4e9190611692565b9050818114610efc575f856001018281548110610e6d57610e6d611652565b905f5260205f2090600891828204019190066004029054906101000a900460e01b905080866001018481548110610ea657610ea6611652565b905f5260205f2090600891828204019190066004026101000a81548163ffffffff021916908360e01c0217905550826001610ee191906116a5565b6001600160e01b03199091165f908152602087905260409020555b6001600160e01b031984165f9081526020869052604081205560018501805480610f2857610f286116b8565b5f8281526020902060085f1990920191820401805463ffffffff600460078516026101000a0219169055905550600191506102fb9050565b505f6102fb565b6001600160e01b031981165f90815260208390526040812054610f6057506001828101805480830182555f82815260208082206008840401805463ffffffff60079095166004026101000a948502191660e088901c949094029390931790925591546001600160e01b031985168352908590526040909120556102fb565b610fee8261121d565b806001600160a01b031661100183610d7f565b6040516001600160e01b0319851681526001600160a01b0391909116907f347b48699b991c95bb339a3a778222488794b19790e9f46171825933c63a9cc49060200160405180910390a3604080516001600160e01b0319939093166020808501919091527f950d7e977b74051843ed988c77d53a700cd967d2ac5480d98dd4c1edaf0b4dc8848301528151808503830181526060909401909152825192019190912055565b60605f6110b383856116a5565b9050838110156111055760405162461bcd60e51b815260206004820152601160248201527f6164646974696f6e206f766572666c6f770000000000000000000000000000006044820152606401610362565b60018501548111611116578061111c565b60018501545b905080158061112b5750808410155b156111365750611216565b6111408482611692565b67ffffffffffffffff8111156111585761115861156b565b604051908082528060200260200182016040528015611181578160200160208202803683370190505b5091505f5b6111908583611692565b81101561121357600186016111a586836116a5565b815481106111b5576111b5611652565b905f5260205f2090600891828204019190066004029054906101000a900460e01b8382815181106111e8576111e8611652565b6001600160e01b0319909216602092830291909101909101528061120b8161167a565b915050611186565b50505b9392505050565b5f6112266112c9565b80519091505f5b818110156112c35782818151811061124757611247611652565b60200260200101516001600160e01b031916846001600160e01b031916036112b15760405162461bcd60e51b815260206004820152601a60248201527f66756e6374696f6e20696420616c7265616479206578697374730000000000006044820152606401610362565b806112bb8161167a565b91505061122d565b50505050565b60408051600880825261012082019092526060915f9190602082016101008036833701905050905063dc9cc64560e01b815f8151811061130b5761130b611652565b6001600160e01b0319909216602092830291909101909101528051636bc26a1360e11b908290600190811061134257611342611652565b6001600160e01b0319909216602092830291909101909101528051630e1cf91b60e01b908290600290811061137957611379611652565b6001600160e01b03199092166020928302919091019091015280516233c04b60e01b90829060039081106113af576113af611652565b6001600160e01b03199092166020928302919091019091015280516332abba4760e21b90829060049081106113e6576113e6611652565b6001600160e01b0319909216602092830291909101909101528051631ab7710d60e01b908290600590811061141d5761141d611652565b6001600160e01b0319909216602092830291909101909101528051638456cb5960e01b908290600690811061145457611454611652565b6001600160e01b0319909216602092830291909101909101528051631fa5d41d60e11b908290600790811061148b5761148b611652565b6001600160e01b031990921660209283029190910190910152919050565b5f80602083850312156114ba575f80fd5b823567ffffffffffffffff808211156114d1575f80fd5b818501915085601f8301126114e4575f80fd5b8135818111156114f2575f80fd5b866020828501011115611503575f80fd5b60209290920196919550909350505050565b5f60208284031215611525575f80fd5b81356001600160a01b0381168114611216575f80fd5b6001600160e01b031981168114610376575f80fd5b5f60208284031215611560575f80fd5b81356112168161153b565b634e487b7160e01b5f52604160045260245ffd5b80516107638161153b565b5f806040838503121561159b575f80fd5b825167ffffffffffffffff808211156115b2575f80fd5b818501915085601f8301126115c5575f80fd5b81516020828211156115d9576115d961156b565b8160051b604051601f19603f830116810181811086821117156115fe576115fe61156b565b60405292835281830193508481018201928984111561161b575f80fd5b948201945b83861015611640576116318661157f565b85529482019493820193611620565b97909101519698969750505050505050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f6001820161168b5761168b611666565b5060010190565b818103818111156102fb576102fb611666565b808201808211156102fb576102fb611666565b634e487b7160e01b5f52603160045260245ffdfeb5f6074d2b374487ffe12d401cf0891c7591a84c4944ef117f69d13b80c4d6d8a264697066735822122090e7122bc8d3ea42235cdf8d59d4687ca19d2c41d243027e640f1c695b907a2664736f6c63430008150033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.