Source Code
Overview
S Balance
More Info
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xBbB9C1E6...552Ca305e The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
DisposableRamm
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.18; import "../../modules/capital/Ramm.sol"; contract DisposableRamm is Ramm { uint internal poolValue; uint internal supply; uint internal bondingCurveTokenPrice; constructor(uint spotPriceB) Ramm(spotPriceB) { // } function initialize( uint _poolValue, uint _totalSupply, uint _bondingCurveTokenPrice ) external { require(slot1.updatedAt == 0, "DisposableRamm: Already initialized"); // initialize values poolValue = _poolValue; supply = _totalSupply; bondingCurveTokenPrice = _bondingCurveTokenPrice; // set dependencies to point to self internalContracts[uint(ID.P1)] = payable(address(this)); internalContracts[uint(ID.TC)] = payable(address(this)); internalContracts[uint(ID.MC)] = payable(address(this)); super.initialize(); slot1.swapPaused = false; } // fake pool functions function getPoolValueInEth() external view returns (uint) { return poolValue; } function totalSupply() external view returns (uint) { return supply; } function getTokenPrice() external view returns (uint) { return bondingCurveTokenPrice; } }
// 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: GPL-3.0-only pragma solidity ^0.8.18; import "../interfaces/ISAFURAMaster.sol"; import "../interfaces/IMasterAwareV2.sol"; import "../interfaces/IMemberRoles.sol"; abstract contract MasterAwareV2 is IMasterAwareV2 { ISAFURAMaster public master; mapping(uint => address payable) public internalContracts; modifier onlyMember { require( IMemberRoles(internalContracts[uint(ID.MR)]).checkRole( msg.sender, uint(IMemberRoles.Role.Member) ), "Caller is not a member" ); _; } modifier onlyAdvisoryBoard { require( IMemberRoles(internalContracts[uint(ID.MR)]).checkRole( msg.sender, uint(IMemberRoles.Role.AdvisoryBoard) ), "Caller is not an advisory board member" ); _; } modifier onlyInternal { require(master.isInternal(msg.sender), "Caller is not an internal contract"); _; } modifier onlyMaster { if (address(master) != address(0)) { require(address(master) == msg.sender, "Not master"); } _; } modifier onlyGovernance { require( master.checkIsAuthToGoverned(msg.sender), "Caller is not authorized to govern" ); _; } modifier onlyEmergencyAdmin { require( msg.sender == master.emergencyAdmin(), "Caller is not emergency admin" ); _; } modifier whenPaused { require(master.isPause(), "System is not paused"); _; } modifier whenNotPaused { require(!master.isPause(), "System is paused"); _; } function getInternalContractAddress(ID id) internal view returns (address payable) { return internalContracts[uint(id)]; } function changeMasterAddress(address masterAddress) public onlyMaster { master = ISAFURAMaster(masterAddress); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface IMasterAwareV2 { // TODO: if you update this enum, update lib/constants.js as well enum ID { TC, // TokenController.sol P1, // Pool.sol MR, // MemberRoles.sol MC, // MCR.sol CO, // Cover.sol SP, // StakingProducts.sol PS, // LegacyPooledStaking.sol GV, // Governance.sol GW, // LegacyGateway.sol - removed CL, // CoverMigrator.sol - removed AS, // Assessment.sol CI, // IndividualClaims.sol - Claims for Individuals CG, // YieldTokenIncidents.sol - Claims for Groups RA, // Ramm.sol ST, // SafeTracker.sol CP // CoverProducts.sol } function changeMasterAddress(address masterAddress) external; function changeDependentContractAddress() external; function internalContracts(uint) external view returns (address payable); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface IMCR { function updateMCRInternal(bool forceUpdate) external; function getMCR() external view returns (uint); function mcr() external view returns (uint80); function desiredMCR() external view returns (uint80); function lastUpdateTime() external view returns (uint32); function maxMCRIncrement() external view returns (uint16); function gearingFactor() external view returns (uint24); function minUpdateTime() external view returns (uint16); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface IMemberRoles { enum Role {Unassigned, AdvisoryBoard, Member, Owner, Auditor} function join(address _userAddress, uint nonce, bytes calldata signature) external payable; function switchMembership(address _newAddress) external; function switchMembershipAndAssets( address newAddress, uint[] calldata coverIds, uint[] calldata stakingTokenIds ) external; function switchMembershipOf(address member, address _newAddress) external; function totalRoles() external view returns (uint256); function changeAuthorized(uint _roleId, address _newAuthorized) external; function setKycAuthAddress(address _add) external; function members(uint _memberRoleId) external view returns (uint, address[] memory memberArray); function numberOfMembers(uint _memberRoleId) external view returns (uint); function authorized(uint _memberRoleId) external view returns (address); function roles(address _memberAddress) external view returns (uint[] memory); function checkRole(address _memberAddress, uint _roleId) external view returns (bool); function getMemberLengthForAllRoles() external view returns (uint[] memory totalMembers); function memberAtIndex(uint _memberRoleId, uint index) external view returns (address, bool); function membersLength(uint _memberRoleId) external view returns (uint); event MemberRole(uint256 indexed roleId, bytes32 roleName, string roleDescription); event MemberJoined(address indexed newMember, uint indexed nonce); event switchedMembership(address indexed previousMember, address indexed newMember, uint timeStamp); event MembershipWithdrawn(address indexed member, uint timestamp); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "./IPriceFeedOracle.sol"; struct SwapDetails { uint104 minAmount; uint104 maxAmount; uint32 lastSwapTime; // 2 decimals of precision. 0.01% -> 0.0001 -> 1e14 uint16 maxSlippageRatio; } struct Asset { address assetAddress; bool isCoverAsset; bool isAbandoned; } interface IPool { function swapOperator() external view returns (address); function getAsset(uint assetId) external view returns (Asset memory); function getAssets() external view returns (Asset[] memory); function transferAssetToSwapOperator(address asset, uint amount) external; function setSwapDetailsLastSwapTime(address asset, uint32 lastSwapTime) external; function getAssetSwapDetails(address assetAddress) external view returns (SwapDetails memory); function sendPayout(uint assetIndex, address payable payoutAddress, uint amount, uint ethDepositAmount) external; function sendEth(address payoutAddress, uint amount) external; function upgradeCapitalPool(address payable newPoolAddress) external; function priceFeedOracle() external view returns (IPriceFeedOracle); function getPoolValueInEth() external view returns (uint); function calculateMCRRatio(uint totalAssetValue, uint mcrEth) external pure returns (uint); function getInternalTokenPriceInAsset(uint assetId) external view returns (uint tokenPrice); function getInternalTokenPriceInAssetAndUpdateTwap(uint assetId) external returns (uint tokenPrice); function getTokenPrice() external view returns (uint tokenPrice); function getMCRRatio() external view returns (uint); function setSwapValue(uint value) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface Aggregator { function decimals() external view returns (uint8); function latestAnswer() external view returns (int); } interface IPriceFeedOracle { struct OracleAsset { Aggregator aggregator; uint8 decimals; } function ETH() external view returns (address); function assets(address) external view returns (Aggregator, uint8); function getAssetToEthRate(address asset) external view returns (uint); function getAssetForEth(address asset, uint ethIn) external view returns (uint); function getEthForAsset(address asset, uint amount) external view returns (uint); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "./IPool.sol"; import "./ISAFURAToken.sol"; import "./ITokenController.sol"; interface IRamm { // storage structs struct Slot0 { uint128 nxmReserveA; uint128 nxmReserveB; } struct Slot1 { uint128 ethReserve; uint88 budget; uint32 updatedAt; bool swapPaused; // emergency pause } struct Observation { uint32 timestamp; uint112 priceCumulativeAbove; uint112 priceCumulativeBelow; } // memory structs struct State { uint nxmA; uint nxmB; uint eth; uint budget; uint ratchetSpeedB; uint timestamp; } struct Context { uint capital; uint supply; uint mcr; } struct CumulativePriceCalculationProps { uint previousEthReserve; uint currentEthReserve; uint previousNxmA; uint currentNxmA; uint previousNxmB; uint currentNxmB; uint previousTimestamp; uint observationTimestamp; } struct CumulativePriceCalculationTimes { uint secondsUntilBVAbove; uint secondsUntilBVBelow; uint timeElapsed; uint bvTimeBelow; uint bvTimeAbove; uint ratchetTimeAbove; uint ratchetTimeBelow; } /* ========== VIEWS ========== */ function getReserves() external view returns ( uint ethReserve, uint nxmA, uint nxmB, uint remainingBudget ); function getSpotPrices() external view returns (uint spotPriceA, uint spotPriceB); function getBookValue() external view returns (uint bookValue); function getInternalPrice() external view returns (uint internalPrice); /* ==== MUTATIVE FUNCTIONS ==== */ function updateTwap() external; function getInternalPriceAndUpdateTwap() external returns (uint internalPrice); function swap(uint nxmIn, uint minAmountOut, uint deadline) external payable returns (uint amountOut); function removeBudget() external; function setEmergencySwapPause(bool _swapPaused) external; /* ========== EVENTS AND ERRORS ========== */ event EthSwappedForNxm(address indexed member, uint ethIn, uint nxmOut); event NxmSwappedForEth(address indexed member, uint nxmIn, uint ethOut); event ObservationUpdated(uint32 timestamp, uint112 priceCumulativeAbove, uint112 priceCumulativeBelow); event BudgetRemoved(); event SwapPauseConfigured(bool paused); event EthInjected(uint value); event EthExtracted(uint value); // Pause error SystemPaused(); error SwapPaused(); // Input error OneInputOnly(); error OneInputRequired(); // Expiry error SwapExpired(uint deadline, uint blockTimestamp); // Insufficient amount out error InsufficientAmountOut(uint amountOut, uint minAmountOut); // Buffer Zone error NoSwapsInBufferZone(); // ETH Transfer error EthTransferFailed(); // Circuit breakers error EthCircuitBreakerHit(); error NxmCircuitBreakerHit(); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface ISAFURAMaster { function tokenAddress() external view returns (address); function owner() external view returns (address); function emergencyAdmin() external view returns (address); function masterInitialized() external view returns (bool); function isInternal(address _add) external view returns (bool); function isPause() external view returns (bool check); function isMember(address _add) external view returns (bool); function checkIsAuthToGoverned(address _add) external view returns (bool); function getLatestAddress(bytes2 _contractName) external view returns (address payable contractAddress); function contractAddresses(bytes2 code) external view returns (address payable); function upgradeMultipleContracts( bytes2[] calldata _contractCodes, address payable[] calldata newAddresses ) external; function removeContracts(bytes2[] calldata contractCodesToRemove) external; function addNewInternalContracts( bytes2[] calldata _contractCodes, address payable[] calldata newAddresses, uint[] calldata _types ) external; function updateOwnerParameters(bytes8 code, address payable val) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; interface ISAFURAToken { function burn(uint256 amount) external returns (bool); function burnFrom(address from, uint256 value) external returns (bool); function operatorTransfer(address from, uint256 value) external returns (bool); function mint(address account, uint256 amount) external; function isLockedForMV(address member) external view returns (uint); function whiteListed(address member) external view returns (bool); function addToWhiteList(address _member) external returns (bool); function removeFromWhiteList(address _member) external returns (bool); function changeOperator(address _newOperator) external returns (bool); function lockForMemberVote(address _of, uint _days) external; /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.5.0; import "./ISAFURAToken.sol"; interface ITokenController { struct StakingPoolNXMBalances { uint128 rewards; uint128 deposits; } struct CoverInfo { uint16 claimCount; bool hasOpenClaim; bool hasAcceptedClaim; uint96 requestedPayoutAmount; // note: still 128 bits available here, can be used later } struct StakingPoolOwnershipOffer { address proposedManager; uint96 deadline; } function coverInfo(uint id) external view returns ( uint16 claimCount, bool hasOpenClaim, bool hasAcceptedClaim, uint96 requestedPayoutAmount ); function withdrawCoverNote( address _of, uint[] calldata _coverIds, uint[] calldata _indexes ) external; function changeOperator(address _newOperator) external; function operatorTransfer(address _from, address _to, uint _value) external returns (bool); function burnFrom(address _of, uint amount) external returns (bool); function addToWhitelist(address _member) external; function removeFromWhitelist(address _member) external; function mint(address _member, uint _amount) external; function lockForMemberVote(address _of, uint _days) external; function withdrawClaimAssessmentTokens(address[] calldata users) external; function getLockReasons(address _of) external view returns (bytes32[] memory reasons); function totalSupply() external view returns (uint); function totalBalanceOf(address _of) external view returns (uint amount); function totalBalanceOfWithoutDelegations(address _of) external view returns (uint amount); function getTokenPrice() external view returns (uint tokenPrice); function token() external view returns (ISAFURAToken); function getStakingPoolManager(uint poolId) external view returns (address manager); function getManagerStakingPools(address manager) external view returns (uint[] memory poolIds); function isStakingPoolManager(address member) external view returns (bool); function getStakingPoolOwnershipOffer(uint poolId) external view returns (address proposedManager, uint deadline); function transferStakingPoolsOwnership(address from, address to) external; function assignStakingPoolManager(uint poolId, address manager) external; function createStakingPoolOwnershipOffer(uint poolId, address proposedManager, uint deadline) external; function acceptStakingPoolOwnershipOffer(uint poolId) external; function cancelStakingPoolOwnershipOffer(uint poolId) external; function mintStakingPoolNXMRewards(uint amount, uint poolId) external; function burnStakingPoolNXMRewards(uint amount, uint poolId) external; function depositStakedNXM(address from, uint amount, uint poolId) external; function withdrawNXMStakeAndRewards(address to, uint stakeToWithdraw, uint rewardsToWithdraw, uint poolId) external; function burnStakedNXM(uint amount, uint poolId) external; function stakingPoolNXMBalances(uint poolId) external view returns(uint128 rewards, uint128 deposits); function tokensLocked(address _of, bytes32 _reason) external view returns (uint256 amount); function getWithdrawableCoverNotes( address coverOwner ) external view returns ( uint[] memory coverIds, bytes32[] memory lockReasons, uint withdrawableAmount ); function getPendingRewards(address member) external view returns (uint); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.18; /** * @dev Simple library that defines min, max and babylonian sqrt functions */ library Math { function min(uint a, uint b) internal pure returns (uint) { return a < b ? a : b; } function max(uint a, uint b) internal pure returns (uint) { return a > b ? a : b; } function sum(uint[] memory items) internal pure returns (uint) { uint count = items.length; uint total; for (uint i = 0; i < count; i++) { total += items[i]; } return total; } function divRound(uint a, uint b) internal pure returns (uint) { return (a + b / 2) / b; } function divCeil(uint a, uint b) internal pure returns (uint) { return (a + b - 1) / b; } function roundUp(uint a, uint b) internal pure returns (uint) { return divCeil(a, b) * b; } // babylonian method function sqrt(uint y) internal pure returns (uint) { if (y > 3) { uint z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } return z; } if (y != 0) { return 1; } return 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; /** * @dev Wrappers over Solidity's uintXX casting operators with added overflow * checks. * * Downcasting from uint256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeUintCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { require(value < 2**248, "SafeCast: value doesn\'t fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { require(value < 2**240, "SafeCast: value doesn\'t fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { require(value < 2**232, "SafeCast: value doesn\'t fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { require(value < 2**224, "SafeCast: value doesn\'t fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { require(value < 2**216, "SafeCast: value doesn\'t fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { require(value < 2**208, "SafeCast: value doesn\'t fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { require(value < 2**200, "SafeCast: value doesn\'t fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { require(value < 2**192, "SafeCast: value doesn\'t fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { require(value < 2**184, "SafeCast: value doesn\'t fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { require(value < 2**176, "SafeCast: value doesn\'t fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { require(value < 2**168, "SafeCast: value doesn\'t fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { require(value < 2**160, "SafeCast: value doesn\'t fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { require(value < 2**152, "SafeCast: value doesn\'t fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { require(value < 2**144, "SafeCast: value doesn\'t fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { require(value < 2**136, "SafeCast: value doesn\'t fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { require(value < 2**120, "SafeCast: value doesn\'t fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { require(value < 2**112, "SafeCast: value doesn\'t fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { require(value < 2**104, "SafeCast: value doesn\'t fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { require(value < 2**96, "SafeCast: value doesn\'t fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { require(value < 2**88, "SafeCast: value doesn\'t fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { require(value < 2**80, "SafeCast: value doesn\'t fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { require(value < 2**56, "SafeCast: value doesn\'t fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { require(value < 2**48, "SafeCast: value doesn\'t fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { require(value < 2**40, "SafeCast: value doesn\'t fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { require(value < 2**24, "SafeCast: value doesn\'t fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits"); return uint8(value); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.18; import "@openzeppelin/contracts-v4/security/ReentrancyGuard.sol"; import "../../abstract/MasterAwareV2.sol"; import "../../interfaces/IMCR.sol"; import "../../interfaces/IPool.sol"; import "../../interfaces/IRamm.sol"; import "../../interfaces/ITokenController.sol"; import "../../libraries/Math.sol"; import "../../libraries/SafeUintCast.sol"; contract Ramm is IRamm, MasterAwareV2, ReentrancyGuard { using SafeUintCast for uint; using Math for uint; /* ========== STATE VARIABLES ========== */ Slot0 public slot0; Slot1 public slot1; // one slot per array item Observation[3] public observations; // circuit breakers slot uint96 public ethReleased; uint32 public ethLimit; uint96 public nxmReleased; uint32 public nxmLimit; /* ========== CONSTANTS ========== */ uint public constant LIQ_SPEED_PERIOD = 1 days; uint public constant RATCHET_PERIOD = 1 days; uint public constant RATCHET_DENOMINATOR = 10_000; uint public constant PRICE_BUFFER = 100; uint public constant PRICE_BUFFER_DENOMINATOR = 10_000; uint public constant GRANULARITY = 3; uint public constant PERIOD_SIZE = 3 days; uint public constant FAST_LIQUIDITY_SPEED = 1_500 ether; uint public constant TARGET_LIQUIDITY = 5_000 ether; uint public constant LIQ_SPEED_A = 100 ether; uint public constant LIQ_SPEED_B = 100 ether; uint public constant NORMAL_RATCHET_SPEED = 400; uint public constant FAST_RATCHET_SPEED = 5_000; uint internal constant INITIAL_LIQUIDITY = 5_000 ether; uint internal constant INITIAL_BUDGET = 43_835 ether; // circuit breakers uint internal constant INITIAL_ETH_LIMIT = 22_000; uint internal constant INITIAL_NXM_LIMIT = 250_000; /* ========== IMMUTABLES ========== */ uint internal immutable SPOT_PRICE_B; /* ========== CONSTRUCTOR ========== */ constructor(uint spotPriceB) { SPOT_PRICE_B = spotPriceB; } function loadState() public view returns (State memory) { return State( slot0.nxmReserveA, slot0.nxmReserveB, slot1.ethReserve, slot1.budget, slot1.budget == 0 ? NORMAL_RATCHET_SPEED : FAST_RATCHET_SPEED, slot1.updatedAt ); } function storeState(State memory state) internal { // slot 0 slot0.nxmReserveA = state.nxmA.toUint128(); slot0.nxmReserveB = state.nxmB.toUint128(); // slot 1 slot1.ethReserve = state.eth.toUint128(); slot1.budget = state.budget.toUint88(); slot1.updatedAt = state.timestamp.toUint32(); } function ratchetSpeedB() external view returns (uint) { return slot1.budget == 0 ? NORMAL_RATCHET_SPEED : FAST_RATCHET_SPEED; } function swapPaused() external view returns (bool) { return slot1.swapPaused; } /** * @notice Swaps nxmIn tokens for ETH or ETH sent for NXM tokens * @param nxmIn The amount of NXM tokens to swap (set to 0 when swapping ETH for NXM) * @param minAmountOut The minimum amount to receive in the swap (reverts with InsufficientAmountOut if not met) * @param deadline The deadline for the swap to be executed (reverts with SwapExpired if deadline is surpassed) * @return amountOut The amount received in the swap */ function swap( uint nxmIn, uint minAmountOut, uint deadline ) external payable nonReentrant returns (uint) { if (msg.value > 0 && nxmIn > 0) { revert OneInputOnly(); } if (msg.value == 0 && nxmIn == 0) { revert OneInputRequired(); } if (block.timestamp > deadline) { revert SwapExpired(deadline, block.timestamp); } Context memory context = Context( pool().getPoolValueInEth(), // capital tokenController().totalSupply(), // supply mcr().getMCR() // mcr ); State memory initialState = loadState(); if (master.isPause()) { revert SystemPaused(); } if (slot1.swapPaused) { revert SwapPaused(); } uint amountOut = msg.value > 0 ? swapEthForNxm(msg.value, minAmountOut, context, initialState) : swapNxmForEth(nxmIn, minAmountOut, context, initialState); if (msg.value > 0) { nxmReleased = (nxmReleased + amountOut).toUint96(); if (nxmLimit > 0 && nxmReleased > uint(nxmLimit) * 1 ether) { revert NxmCircuitBreakerHit(); } } else { ethReleased = (ethReleased + amountOut).toUint96(); if (ethLimit > 0 && ethReleased > uint(ethLimit) * 1 ether) { revert EthCircuitBreakerHit(); } } mcr().updateMCRInternal(false); return amountOut; } /** * @dev should only be called by swap */ function swapEthForNxm( uint ethIn, uint minAmountOut, Context memory context, State memory initialState ) internal returns (uint nxmOut) { Observation[3] memory _observations = observations; // current state ( State memory state, uint injected, uint extracted ) = _getReserves(initialState, context, block.timestamp); _observations = _updateTwap(initialState, _observations, context, block.timestamp); { uint k = state.eth * state.nxmA; uint newEth = state.eth + ethIn; uint newNxmA = k / newEth; uint newNxmB = state.nxmB * newEth / state.eth; nxmOut = state.nxmA - newNxmA; if (nxmOut < minAmountOut) { revert InsufficientAmountOut(nxmOut, minAmountOut); } // edge case: below goes over bv due to eth-dai price changing state.nxmA = newNxmA; state.nxmB = newNxmB; state.eth = newEth; state.timestamp = block.timestamp; } storeState(state); if (injected > 0) { emit EthInjected(injected); } if (extracted > 0) { emit EthExtracted(extracted); } for (uint i = 0; i < _observations.length; i++) { observations[i] = _observations[i]; } // transfer assets (bool ok,) = address(pool()).call{value: msg.value}(""); if (ok != true) { revert EthTransferFailed(); } tokenController().mint(msg.sender, nxmOut); emit EthSwappedForNxm(msg.sender, ethIn, nxmOut); return nxmOut; } /** * @dev should only be called by swap */ function swapNxmForEth( uint nxmIn, uint minAmountOut, Context memory context, State memory initialState ) internal returns (uint ethOut) { Observation[3] memory _observations = observations; // current state ( State memory state, uint injected, uint extracted ) = _getReserves(initialState, context, block.timestamp); _observations = _updateTwap(initialState, _observations, context, block.timestamp); { uint k = state.eth * state.nxmB; uint newNxmB = state.nxmB + nxmIn; uint newEth = k / newNxmB; uint newNxmA = state.nxmA * newEth / state.eth; ethOut = state.eth - newEth; if (ethOut < minAmountOut) { revert InsufficientAmountOut(ethOut, minAmountOut); } if (context.capital - ethOut < context.mcr) { revert NoSwapsInBufferZone(); } // update storage state.nxmA = newNxmA; state.nxmB = newNxmB; state.eth = newEth; state.timestamp = block.timestamp; } storeState(state); if (injected > 0) { emit EthInjected(injected); } if (extracted > 0) { emit EthExtracted(extracted); } for (uint i = 0; i < _observations.length; i++) { observations[i] = _observations[i]; } tokenController().burnFrom(msg.sender, nxmIn); pool().sendEth(msg.sender, ethOut); emit NxmSwappedForEth(msg.sender, nxmIn, ethOut); return ethOut; } /** * @notice Sets the budget to 0 * @dev Can only be called by governance */ function removeBudget() external onlyGovernance { slot1.budget = 0; emit BudgetRemoved(); } /** * @notice Sets swap emergency pause * @dev Can only be called by the emergency admin * @param _swapPaused to toggle swap emergency pause ON/OFF */ function setEmergencySwapPause(bool _swapPaused) external onlyEmergencyAdmin { slot1.swapPaused = _swapPaused; emit SwapPauseConfigured(_swapPaused); } function setCircuitBreakerLimits( uint _ethLimit, uint _nxmLimit ) external onlyEmergencyAdmin { ethLimit = _ethLimit.toUint32(); nxmLimit = _nxmLimit.toUint32(); } /* ============== VIEWS ============= */ /** * @notice Retrieves the current reserves of the RAMM contract * @return _ethReserve The current ETH reserve * @return nxmA The current NXM buy price * @return nxmB The current NXM sell price * @return _budget The current ETH budget used for injection */ function getReserves() external view returns (uint _ethReserve, uint nxmA, uint nxmB, uint _budget) { Context memory context = Context( pool().getPoolValueInEth(), // capital tokenController().totalSupply(), // supply mcr().getMCR() // mcr ); ( State memory state, /* injected */, /* extracted */ ) = _getReserves(loadState(), context, block.timestamp); return (state.eth, state.nxmA, state.nxmB, state.budget); } function calculateInjected( uint eth, uint budget, Context memory context, uint elapsed ) internal pure returns (uint) { uint timeLeftOnBudget = budget * LIQ_SPEED_PERIOD / FAST_LIQUIDITY_SPEED; uint maxToInject = (context.capital > context.mcr + TARGET_LIQUIDITY) ? Math.min(TARGET_LIQUIDITY - eth, context.capital - context.mcr - TARGET_LIQUIDITY) : 0; if (elapsed <= timeLeftOnBudget) { return Math.min(elapsed * FAST_LIQUIDITY_SPEED / LIQ_SPEED_PERIOD, maxToInject); } uint injectedFast = timeLeftOnBudget * FAST_LIQUIDITY_SPEED / LIQ_SPEED_PERIOD; uint injectedSlow = (elapsed - timeLeftOnBudget) * LIQ_SPEED_B / LIQ_SPEED_PERIOD; return Math.min(maxToInject, injectedFast + injectedSlow); } function adjustEth( uint eth, uint budget, Context memory context, uint elapsed ) internal pure returns (uint /* new eth */, uint /* new budget */, uint injected, uint extracted) { if (eth < TARGET_LIQUIDITY) { injected = calculateInjected(eth, budget, context, elapsed); eth += injected; budget = budget > injected ? budget - injected : 0; } else { extracted = Math.min((elapsed * LIQ_SPEED_A) / LIQ_SPEED_PERIOD, eth - TARGET_LIQUIDITY); eth -= extracted; } return (eth, budget, injected, extracted); } function calculateNxm( State memory state, uint eth, uint elapsed, Context memory context, bool isAbove ) internal pure returns (uint) { uint stateNxm = isAbove ? state.nxmA : state.nxmB; uint nxm = stateNxm * eth / state.eth; uint buffer = isAbove ? PRICE_BUFFER_DENOMINATOR + PRICE_BUFFER : PRICE_BUFFER_DENOMINATOR - PRICE_BUFFER; uint bufferedCapital = context.capital * buffer / PRICE_BUFFER_DENOMINATOR; if (isAbove) { // ratchet above // cap*n*(1+r) > e*sup // cap*n + cap*n*r > e*sup // ? set n(new) = n(BV) // : set n(new) = n(R) return bufferedCapital * nxm + bufferedCapital * nxm * elapsed * NORMAL_RATCHET_SPEED / RATCHET_PERIOD / RATCHET_DENOMINATOR > eth * context.supply ? eth * context.supply / bufferedCapital // bv : eth * nxm / (eth - context.capital * nxm * elapsed * NORMAL_RATCHET_SPEED / context.supply / RATCHET_PERIOD / RATCHET_DENOMINATOR); // ratchet } // ratchet below // check if we should be using the ratchet or the book value price using: // Nbv > Nr <=> // ... <=> // cap*n < e*sup + cap*n*r // ? set n(new) = n(BV) // : set n(new) = n(R) return bufferedCapital * nxm < eth * context.supply + context.capital * nxm * elapsed * state.ratchetSpeedB / RATCHET_PERIOD / RATCHET_DENOMINATOR ? eth * context.supply / bufferedCapital // bv : eth * nxm / (eth + context.capital * nxm * elapsed * state.ratchetSpeedB/ context.supply / RATCHET_PERIOD / RATCHET_DENOMINATOR); // ratchet } function _getReserves( State memory state, Context memory context, uint currentTimestamp ) public pure returns (State memory /* new state */, uint injected, uint extracted) { uint eth = state.eth; uint budget = state.budget; uint elapsed = currentTimestamp - state.timestamp; (eth, budget, injected, extracted) = adjustEth(eth, budget, context, elapsed); uint nxmA = calculateNxm(state, eth, elapsed, context, true); uint nxmB = calculateNxm(state, eth, elapsed, context, false); return ( State(nxmA, nxmB, eth, budget, state.ratchetSpeedB, currentTimestamp), injected, extracted ); } /** * @notice Retrieves the current NXM spot prices * @return spotPriceA The current NXM buy price * @return spotPriceB The current NXM sell price */ function getSpotPrices() external view returns (uint spotPriceA, uint spotPriceB) { Context memory context = Context( pool().getPoolValueInEth(), // capital tokenController().totalSupply(), // supply mcr().getMCR() // mcr ); ( State memory state, /* injected */, /* extracted */ ) = _getReserves(loadState(), context, block.timestamp); return ( 1 ether * state.eth / state.nxmA, 1 ether * state.eth / state.nxmB ); } /** * @notice Retrieves the current NXM book value * @return bookValue the current NXM book value */ function getBookValue() external view returns (uint bookValue) { uint capital = pool().getPoolValueInEth(); uint supply = tokenController().totalSupply(); return 1 ether * capital / supply; } /* ========== ORACLE ========== */ function observationIndexOf(uint timestamp) internal pure returns (uint index) { return timestamp.divCeil(PERIOD_SIZE) % GRANULARITY; } function calculateTimeOnRatchetAndBV( State memory previousState, uint timeElapsed, uint stateRatchetSpeedB, uint supply, uint capital, bool isAbove ) internal pure returns (uint timeOnRatchet, uint timeOnBV) { // Formula to find out how much time it takes for ratchet price to hit BV + buffer // // above: // inner = (eth * supply) - (buffer * capital * nxm) // // below: // inner = (buffer * capital * nxm) - (eth * supply) // // [inner * denom * period] / (capital * nxm * speed) uint prevNxm = isAbove ? previousState.nxmA : previousState.nxmB; uint currentRatchetSpeed = isAbove ? NORMAL_RATCHET_SPEED : stateRatchetSpeedB; uint bufferMultiplier = isAbove ? (PRICE_BUFFER_DENOMINATOR + PRICE_BUFFER) : (PRICE_BUFFER_DENOMINATOR - PRICE_BUFFER); uint inner; { uint ethTerm = previousState.eth * supply; uint nxmTerm = bufferMultiplier * capital * prevNxm / PRICE_BUFFER_DENOMINATOR; uint innerLeft = isAbove ? ethTerm : nxmTerm; uint innerRight = isAbove ? nxmTerm : ethTerm; inner = innerLeft > innerRight ? innerLeft - innerRight : 0; } uint maxTimeOnRatchet = inner != 0 ? (inner * RATCHET_DENOMINATOR * RATCHET_PERIOD) / (capital * prevNxm * currentRatchetSpeed) : 0; timeOnRatchet = Math.min(timeElapsed, maxTimeOnRatchet); timeOnBV = timeElapsed - timeOnRatchet; return (timeOnRatchet, timeOnBV); } function calculatePriceCumulative( State memory previousState, State memory state, uint timeElapsed, uint capital, uint supply, bool isAbove ) internal pure returns (uint) { // average price // pe - previous eth // pn - previous nxm // ce - current eth // cn - current nxm // // P = (pe / pn + ce / cn) / 2 // = (pe * cn + ce * pn) / (2 * pn * cn) // // cumulative price = P * time_on_ratchet // = (pe * cn + ce * pn) * time_on_ratchet / (2 * pn * cn) // cumulative price on bv +- buffer // (time_total - time_on_ratchet) * bv * buffer uint cumulativePrice = 0; (uint timeOnRatchet, uint timeOnBV) = calculateTimeOnRatchetAndBV( previousState, timeElapsed, state.ratchetSpeedB, supply, capital, isAbove ); if (timeOnRatchet != 0) { uint prevNxm = isAbove ? previousState.nxmA : previousState.nxmB; uint currentNxm = isAbove ? state.nxmA : state.nxmB; cumulativePrice += 1 ether * (previousState.eth * currentNxm + state.eth * prevNxm) * timeOnRatchet / (prevNxm * currentNxm * 2); } if (timeOnBV != 0) { uint bufferMultiplier = isAbove ? (PRICE_BUFFER_DENOMINATOR + PRICE_BUFFER) : (PRICE_BUFFER_DENOMINATOR - PRICE_BUFFER); cumulativePrice += 1 ether * timeOnBV * capital * bufferMultiplier / (supply * PRICE_BUFFER_DENOMINATOR); } return cumulativePrice; } function getObservation( State memory previousState, State memory state, Observation memory previousObservation, uint capital, uint supply ) public pure returns (Observation memory) { uint timeElapsed = state.timestamp - previousState.timestamp; uint priceCumulativeAbove = calculatePriceCumulative( previousState, state, timeElapsed, capital, supply, true ); uint priceCumulativeBelow = calculatePriceCumulative( previousState, state, timeElapsed, capital, supply, false ); return Observation( state.timestamp.toUint32(), // casting unsafely to allow overflow uint112(priceCumulativeAbove + previousObservation.priceCumulativeAbove), uint112(priceCumulativeBelow + previousObservation.priceCumulativeBelow) ); } function getInitialObservations( uint initialPriceA, uint initialPriceB, uint timestamp ) public pure returns (Observation[3] memory initialObservations) { uint priceCumulativeAbove; uint priceCumulativeBelow; uint endIdx = timestamp.divCeil(PERIOD_SIZE); uint previousTimestamp = (endIdx - 11) * PERIOD_SIZE; // 27 days | 3 days | until the deployments for (uint idx = endIdx - 2; idx <= endIdx; idx++) { uint observationTimestamp = Math.min(timestamp, idx * PERIOD_SIZE); uint observationIndex = idx % GRANULARITY; uint timeElapsed = observationTimestamp - previousTimestamp; priceCumulativeAbove += initialPriceA * timeElapsed; priceCumulativeBelow += initialPriceB * timeElapsed; initialObservations[observationIndex] = Observation( observationTimestamp.toUint32(), uint112(priceCumulativeAbove), uint112(priceCumulativeBelow) ); previousTimestamp = observationTimestamp; } return initialObservations; } /** * @notice Updates the Time-Weighted Average Price (TWAP) by registering new price observations */ function updateTwap() external { State memory initialState = loadState(); if (initialState.timestamp == block.timestamp) { // already updated return; } Context memory context = Context( pool().getPoolValueInEth(), // capital tokenController().totalSupply(), // supply mcr().getMCR() // mcr ); Observation[3] memory _observations = observations; // current state ( State memory state, uint injected, uint extracted ) = _getReserves(initialState, context, block.timestamp); _observations = _updateTwap(initialState, _observations, context, block.timestamp); for (uint i = 0; i < _observations.length; i++) { observations[i] = _observations[i]; emit ObservationUpdated( observations[i].timestamp, observations[i].priceCumulativeAbove, observations[i].priceCumulativeBelow ); } storeState(state); if (injected > 0) { emit EthInjected(injected); } if (extracted > 0) { emit EthExtracted(extracted); } } function _updateTwap( State memory initialState, Observation[3] memory _observations, Context memory context, uint currentStateTimestamp ) public pure returns (Observation[3] memory) { uint endIdx = currentStateTimestamp.divCeil(PERIOD_SIZE); State memory previousState = initialState; Observation memory previousObservation = _observations[observationIndexOf(initialState.timestamp)]; Observation[3] memory newObservations; for (uint idx = endIdx - 2; idx <= endIdx; idx++) { uint observationTimestamp = Math.min(currentStateTimestamp, idx * PERIOD_SIZE); uint observationIndex = idx % GRANULARITY; if (observationTimestamp <= previousState.timestamp) { newObservations[observationIndex] = Observation( _observations[observationIndex].timestamp, _observations[observationIndex].priceCumulativeAbove, _observations[observationIndex].priceCumulativeBelow ); continue; } ( State memory state, /* injected */, /* extracted */ ) = _getReserves(previousState, context, observationTimestamp); newObservations[observationIndex] = getObservation( previousState, state, previousObservation, context.capital, context.supply ); previousState = state; previousObservation = newObservations[observationIndex]; } return newObservations; } function getInternalPriceAndUpdateTwap() external returns (uint internalPrice) { Context memory context = Context( pool().getPoolValueInEth(), // capital tokenController().totalSupply(), // supply mcr().getMCR() // mcr ); State memory initialState = loadState(); Observation[3] memory _observations = observations; // current state ( State memory state, uint injected, uint extracted ) = _getReserves(initialState, context, block.timestamp); _observations = _updateTwap(initialState, _observations, context, block.timestamp); // sstore observations and state for (uint i = 0; i < _observations.length; i++) { observations[i] = _observations[i]; emit ObservationUpdated( observations[i].timestamp, observations[i].priceCumulativeAbove, observations[i].priceCumulativeBelow ); } storeState(state); if (injected > 0) { emit EthInjected(injected); } if (extracted > 0) { emit EthExtracted(extracted); } return _getInternalPrice(state, _observations, context.capital, context.supply, block.timestamp); } function _getInternalPrice( State memory state, Observation[3] memory _observations, uint capital, uint supply, uint timestamp ) public pure returns (uint) { uint currentIdx = observationIndexOf(timestamp); // index of first observation in window = current - 2 // adding 1 and applying modulo gives the same result avoiding underflow Observation memory firstObservation = _observations[(currentIdx + 1) % GRANULARITY]; Observation memory currentObservation = _observations[currentIdx]; uint spotPriceA = 1 ether * state.eth / state.nxmA; uint spotPriceB = 1 ether * state.eth / state.nxmB; uint internalPrice; // underflow is desired unchecked { uint elapsed = timestamp - firstObservation.timestamp; uint averagePriceA = uint(currentObservation.priceCumulativeAbove - firstObservation.priceCumulativeAbove) / elapsed; uint averagePriceB = uint(currentObservation.priceCumulativeBelow - firstObservation.priceCumulativeBelow) / elapsed; // keeping min/max inside unchecked scope to avoid stack too deep error uint priceA = Math.min(averagePriceA, spotPriceA); uint priceB = Math.max(averagePriceB, spotPriceB); internalPrice = priceA + priceB - 1 ether * capital / supply; } uint maxPrice = 3 * 1 ether * capital / supply; // 300% BV uint minPrice = 35 * 1 ether * capital / supply / 100; // 35% BV internalPrice = Math.max(Math.min(internalPrice, maxPrice), minPrice); return internalPrice; } function getInternalPrice() external view returns (uint internalPrice) { Context memory context = Context( pool().getPoolValueInEth(), // capital tokenController().totalSupply(), // supply mcr().getMCR() // mcr ); State memory initialState = loadState(); Observation[3] memory _observations = observations; ( State memory state, /* injected */, /* extracted */ ) = _getReserves(initialState, context, block.timestamp); _observations = _updateTwap(initialState, _observations, context, block.timestamp); return _getInternalPrice(state, _observations, context.capital, context.supply, block.timestamp); } /* ========== DEPENDENCIES ========== */ function pool() internal view returns (IPool) { return IPool(internalContracts[uint(ID.P1)]); } function mcr() internal view returns (IMCR) { return IMCR(internalContracts[uint(ID.MC)]); } function tokenController() internal view returns (ITokenController) { return ITokenController(internalContracts[uint(ID.TC)]); } function changeDependentContractAddress() external override { internalContracts[uint(ID.P1)] = master.getLatestAddress("P1"); internalContracts[uint(ID.TC)] = master.getLatestAddress("TC"); internalContracts[uint(ID.MC)] = master.getLatestAddress("MC"); initialize(); } function initialize() internal { if (slot1.updatedAt != 0) { // already initialized return; } uint capital = pool().getPoolValueInEth(); uint supply = tokenController().totalSupply(); uint bondingCurvePrice = pool().getTokenPrice(); uint initialPriceA = bondingCurvePrice + 1 ether * capital * PRICE_BUFFER / PRICE_BUFFER_DENOMINATOR / supply; uint initialPriceB = 1 ether * capital * (PRICE_BUFFER_DENOMINATOR - PRICE_BUFFER) / PRICE_BUFFER_DENOMINATOR / supply; uint128 nxmReserveA = (INITIAL_LIQUIDITY * 1 ether / initialPriceA).toUint128(); uint128 nxmReserveB = (INITIAL_LIQUIDITY * 1 ether / SPOT_PRICE_B).toUint128(); uint128 ethReserve = INITIAL_LIQUIDITY.toUint128(); uint88 budget = INITIAL_BUDGET.toUint88(); uint _ratchetSpeedB = FAST_RATCHET_SPEED; uint32 updatedAt = block.timestamp.toUint32(); ethLimit = INITIAL_ETH_LIMIT.toUint32(); nxmLimit = INITIAL_NXM_LIMIT.toUint32(); // start paused slot1.swapPaused = true; State memory state = State( nxmReserveA, nxmReserveB, ethReserve, budget, _ratchetSpeedB, updatedAt ); storeState(state); Observation[3] memory _observations = getInitialObservations(initialPriceA, initialPriceB, updatedAt); for (uint i = 0; i < _observations.length; i++) { observations[i] = _observations[i]; } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"spotPriceB","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EthCircuitBreakerHit","type":"error"},{"inputs":[],"name":"EthTransferFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"InsufficientAmountOut","type":"error"},{"inputs":[],"name":"NoSwapsInBufferZone","type":"error"},{"inputs":[],"name":"NxmCircuitBreakerHit","type":"error"},{"inputs":[],"name":"OneInputOnly","type":"error"},{"inputs":[],"name":"OneInputRequired","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"}],"name":"SwapExpired","type":"error"},{"inputs":[],"name":"SwapPaused","type":"error"},{"inputs":[],"name":"SystemPaused","type":"error"},{"anonymous":false,"inputs":[],"name":"BudgetRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"EthExtracted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"EthInjected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"member","type":"address"},{"indexed":false,"internalType":"uint256","name":"ethIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nxmOut","type":"uint256"}],"name":"EthSwappedForNxm","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"member","type":"address"},{"indexed":false,"internalType":"uint256","name":"nxmIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethOut","type":"uint256"}],"name":"NxmSwappedForEth","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"timestamp","type":"uint32"},{"indexed":false,"internalType":"uint112","name":"priceCumulativeAbove","type":"uint112"},{"indexed":false,"internalType":"uint112","name":"priceCumulativeBelow","type":"uint112"}],"name":"ObservationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"SwapPauseConfigured","type":"event"},{"inputs":[],"name":"FAST_LIQUIDITY_SPEED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FAST_RATCHET_SPEED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GRANULARITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIQ_SPEED_A","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIQ_SPEED_B","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIQ_SPEED_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NORMAL_RATCHET_SPEED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERIOD_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_BUFFER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_BUFFER_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATCHET_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATCHET_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TARGET_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nxmA","type":"uint256"},{"internalType":"uint256","name":"nxmB","type":"uint256"},{"internalType":"uint256","name":"eth","type":"uint256"},{"internalType":"uint256","name":"budget","type":"uint256"},{"internalType":"uint256","name":"ratchetSpeedB","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct IRamm.State","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint112","name":"priceCumulativeAbove","type":"uint112"},{"internalType":"uint112","name":"priceCumulativeBelow","type":"uint112"}],"internalType":"struct IRamm.Observation[3]","name":"_observations","type":"tuple[3]"},{"internalType":"uint256","name":"capital","type":"uint256"},{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"_getInternalPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nxmA","type":"uint256"},{"internalType":"uint256","name":"nxmB","type":"uint256"},{"internalType":"uint256","name":"eth","type":"uint256"},{"internalType":"uint256","name":"budget","type":"uint256"},{"internalType":"uint256","name":"ratchetSpeedB","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct IRamm.State","name":"state","type":"tuple"},{"components":[{"internalType":"uint256","name":"capital","type":"uint256"},{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"mcr","type":"uint256"}],"internalType":"struct IRamm.Context","name":"context","type":"tuple"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"}],"name":"_getReserves","outputs":[{"components":[{"internalType":"uint256","name":"nxmA","type":"uint256"},{"internalType":"uint256","name":"nxmB","type":"uint256"},{"internalType":"uint256","name":"eth","type":"uint256"},{"internalType":"uint256","name":"budget","type":"uint256"},{"internalType":"uint256","name":"ratchetSpeedB","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct IRamm.State","name":"","type":"tuple"},{"internalType":"uint256","name":"injected","type":"uint256"},{"internalType":"uint256","name":"extracted","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nxmA","type":"uint256"},{"internalType":"uint256","name":"nxmB","type":"uint256"},{"internalType":"uint256","name":"eth","type":"uint256"},{"internalType":"uint256","name":"budget","type":"uint256"},{"internalType":"uint256","name":"ratchetSpeedB","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct IRamm.State","name":"initialState","type":"tuple"},{"components":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint112","name":"priceCumulativeAbove","type":"uint112"},{"internalType":"uint112","name":"priceCumulativeBelow","type":"uint112"}],"internalType":"struct IRamm.Observation[3]","name":"_observations","type":"tuple[3]"},{"components":[{"internalType":"uint256","name":"capital","type":"uint256"},{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"mcr","type":"uint256"}],"internalType":"struct IRamm.Context","name":"context","type":"tuple"},{"internalType":"uint256","name":"currentStateTimestamp","type":"uint256"}],"name":"_updateTwap","outputs":[{"components":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint112","name":"priceCumulativeAbove","type":"uint112"},{"internalType":"uint112","name":"priceCumulativeBelow","type":"uint112"}],"internalType":"struct IRamm.Observation[3]","name":"","type":"tuple[3]"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"changeDependentContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"masterAddress","type":"address"}],"name":"changeMasterAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ethLimit","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethReleased","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBookValue","outputs":[{"internalType":"uint256","name":"bookValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"initialPriceA","type":"uint256"},{"internalType":"uint256","name":"initialPriceB","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getInitialObservations","outputs":[{"components":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint112","name":"priceCumulativeAbove","type":"uint112"},{"internalType":"uint112","name":"priceCumulativeBelow","type":"uint112"}],"internalType":"struct IRamm.Observation[3]","name":"initialObservations","type":"tuple[3]"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getInternalPrice","outputs":[{"internalType":"uint256","name":"internalPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInternalPriceAndUpdateTwap","outputs":[{"internalType":"uint256","name":"internalPrice","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nxmA","type":"uint256"},{"internalType":"uint256","name":"nxmB","type":"uint256"},{"internalType":"uint256","name":"eth","type":"uint256"},{"internalType":"uint256","name":"budget","type":"uint256"},{"internalType":"uint256","name":"ratchetSpeedB","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct IRamm.State","name":"previousState","type":"tuple"},{"components":[{"internalType":"uint256","name":"nxmA","type":"uint256"},{"internalType":"uint256","name":"nxmB","type":"uint256"},{"internalType":"uint256","name":"eth","type":"uint256"},{"internalType":"uint256","name":"budget","type":"uint256"},{"internalType":"uint256","name":"ratchetSpeedB","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct IRamm.State","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint112","name":"priceCumulativeAbove","type":"uint112"},{"internalType":"uint112","name":"priceCumulativeBelow","type":"uint112"}],"internalType":"struct IRamm.Observation","name":"previousObservation","type":"tuple"},{"internalType":"uint256","name":"capital","type":"uint256"},{"internalType":"uint256","name":"supply","type":"uint256"}],"name":"getObservation","outputs":[{"components":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint112","name":"priceCumulativeAbove","type":"uint112"},{"internalType":"uint112","name":"priceCumulativeBelow","type":"uint112"}],"internalType":"struct IRamm.Observation","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPoolValueInEth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint256","name":"_ethReserve","type":"uint256"},{"internalType":"uint256","name":"nxmA","type":"uint256"},{"internalType":"uint256","name":"nxmB","type":"uint256"},{"internalType":"uint256","name":"_budget","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSpotPrices","outputs":[{"internalType":"uint256","name":"spotPriceA","type":"uint256"},{"internalType":"uint256","name":"spotPriceB","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolValue","type":"uint256"},{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"uint256","name":"_bondingCurveTokenPrice","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"internalContracts","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"loadState","outputs":[{"components":[{"internalType":"uint256","name":"nxmA","type":"uint256"},{"internalType":"uint256","name":"nxmB","type":"uint256"},{"internalType":"uint256","name":"eth","type":"uint256"},{"internalType":"uint256","name":"budget","type":"uint256"},{"internalType":"uint256","name":"ratchetSpeedB","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct IRamm.State","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"master","outputs":[{"internalType":"contract ISAFURAMaster","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nxmLimit","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nxmReleased","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"observations","outputs":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint112","name":"priceCumulativeAbove","type":"uint112"},{"internalType":"uint112","name":"priceCumulativeBelow","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ratchetSpeedB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"removeBudget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethLimit","type":"uint256"},{"internalType":"uint256","name":"_nxmLimit","type":"uint256"}],"name":"setCircuitBreakerLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_swapPaused","type":"bool"}],"name":"setEmergencySwapPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slot0","outputs":[{"internalType":"uint128","name":"nxmReserveA","type":"uint128"},{"internalType":"uint128","name":"nxmReserveB","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"slot1","outputs":[{"internalType":"uint128","name":"ethReserve","type":"uint128"},{"internalType":"uint88","name":"budget","type":"uint88"},{"internalType":"uint32","name":"updatedAt","type":"uint32"},{"internalType":"bool","name":"swapPaused","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nxmIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"swapPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateTwap","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Deployed Bytecode
0x60806040526004361061027d5760003560e01c80636142c9061161014f578063cc4d0ee6116100c1578063ecb296e51161007a578063ecb296e514610625578063ee6e35fe1461083f578063ee97f7f314610861578063f636c89614610711578063f891743414610881578063fc9654ab1461089657600080fd5b8063cc4d0ee614610772578063d46655f414610792578063d8e7c717146106fa578063dd8cf963146107b2578063e0025664146107dc578063eb962360146107f157600080fd5b80639d9892cd116101135780639d9892cd146106ba578063adf6ce45146106cd578063b738a307146106fa578063b7cc16d814610711578063c54612501461072e578063c87955381461075257600080fd5b80636142c9061461063b57806380d859111461065b5780638516e6dc1461067b5780638ac684fe146106905780639cf29951146106a557600080fd5b80632f04d798116101f35780634b94f50e116101ac5780634b94f50e1461056557806351e8b5c61461057a5780635c448777146105b35780635c95eb52146105c85780635e37b9aa146105e65780635e61f5861461062557600080fd5b80632f04d79814610483578063309f627c1461049857806330e134dc146104b8578063379377a9146104cd5780633850c7bd146104fa5780634a53f3c51461054557600080fd5b806318d458341161024557806318d458341461033b5780631bf7aa89146103505780631f457cb514610366578063245a4e72146103f0578063252c09d71461041a5780632b4186761461046657600080fd5b80630902f1ac1461028257806309f221ee146102bc5780630c474d22146102e05780630ea9c9841461030f57806318160ddd14610326575b600080fd5b34801561028e57600080fd5b506102976108ad565b6040805194855260208501939093529183015260608201526080015b60405180910390f35b3480156102c857600080fd5b506102d261019081565b6040519081526020016102b3565b3480156102ec57600080fd5b506103006102fb36600461408e565b610a41565b6040516102b3939291906140ce565b34801561031b57600080fd5b50610324610b19565b005b34801561033257600080fd5b50600a546102d2565b34801561034757600080fd5b506102d2610d37565b34801561035c57600080fd5b506102d261138881565b34801561037257600080fd5b506004546103b1906001600160801b03811690600160801b81046001600160581b031690600160d81b810463ffffffff1690600160f81b900460ff1684565b604080516001600160801b0390951685526001600160581b03909316602085015263ffffffff90911691830191909152151560608201526080016102b3565b3480156103fc57600080fd5b50600454600160f81b900460ff1660405190151581526020016102b3565b34801561042657600080fd5b5061043a610435366004614123565b6110f2565b6040805163ffffffff90941684526001600160701b0392831660208501529116908201526060016102b3565b34801561047257600080fd5b506102d2685150ae84a8cdf0000081565b34801561048f57600080fd5b506009546102d2565b3480156104a457600080fd5b506102d26104b336600461420d565b61112a565b3480156104c457600080fd5b506102d2606481565b3480156104d957600080fd5b506104ed6104e8366004614260565b6112ef565b6040516102b391906142b1565b34801561050657600080fd5b50600354610525906001600160801b0380821691600160801b90041682565b604080516001600160801b039384168152929091166020830152016102b3565b34801561055157600080fd5b50610324610560366004614317565b6114a4565b34801561057157600080fd5b50600b546102d2565b34801561058657600080fd5b5060085461059e90600160601b900463ffffffff1681565b60405163ffffffff90911681526020016102b3565b3480156105bf57600080fd5b506103246115d4565b3480156105d457600080fd5b506102d269010f0cf064dd5920000081565b3480156105f257600080fd5b5060085461060d90600160801b90046001600160601b031681565b6040516001600160601b0390911681526020016102b3565b34801561063157600080fd5b506102d261271081565b34801561064757600080fd5b5061032461065636600461434a565b6116d9565b34801561066757600080fd5b50610324610676366004614367565b611808565b34801561068757600080fd5b5061032461192f565b34801561069c57600080fd5b506102d2600381565b3480156106b157600080fd5b506102d2611cdf565b6102d26106c8366004614367565b611d08565b3480156106d957600080fd5b506106ed6106e8366004614393565b612212565b6040516102b391906143ef565b34801561070657600080fd5b506102d26201518081565b34801561071d57600080fd5b506102d268056bc75e2d6310000081565b34801561073a57600080fd5b5060085461059e90600160e01b900463ffffffff1681565b34801561075e57600080fd5b5060085461060d906001600160601b031681565b34801561077e57600080fd5b506104ed61078d366004614367565b6122e8565b34801561079e57600080fd5b506103246107ad36600461443b565b61240b565b3480156107be57600080fd5b506107c7612485565b604080519283526020830191909152016102b3565b3480156107e857600080fd5b506102d2612644565b3480156107fd57600080fd5b5061082761080c366004614123565b6001602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016102b3565b34801561084b57600080fd5b50610854612857565b6040516102b39190614458565b34801561086d57600080fd5b50600054610827906001600160a01b031681565b34801561088d57600080fd5b506102d261290d565b3480156108a257600080fd5b506102d26203f48081565b600080600080600060405180606001604052806108c8612a0c565b6001600160a01b0316632f04d7986040518163ffffffff1660e01b8152600401602060405180830381865afa158015610905573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610929919061449b565b8152602001610936612a32565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610973573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610997919061449b565b81526020016109a4612a3d565b6001600160a01b03166344936b106040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a05919061449b565b905290506000610a1d610a16612857565b8342610a41565b50506040810151815160208301516060909301519199909850919650945092505050565b610a7a6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040840151606085015160a0860151600092839290918390610a9c90886144ca565b9050610aaa83838a84612a49565b909750955090935091506000610ac48a85848c6001612af0565b90506000610ad68b86858d6000612af0565b90506040518060c001604052808381526020018281526020018681526020018581526020018c6080015181526020018a8152509750505050505093509350939050565b6000546040516227050b60e31b815261503160f01b60048201526001600160a01b0390911690630138285890602401602060405180830381865afa158015610b65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8991906144dd565b600160008181526020919091527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80546001600160a01b039384166001600160a01b0319909116179055546040516227050b60e31b815261544360f01b6004820152911690630138285890602401602060405180830381865afa158015610c14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3891906144dd565b600080805260016020527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980546001600160a01b039384166001600160a01b0319909116179055546040516227050b60e31b8152614d4360f01b6004820152911690630138285890602401602060405180830381865afa158015610cc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce491906144dd565b600360005260016020527f7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b80546001600160a01b0319166001600160a01b0392909216919091179055610d35612d82565b565b6000806040518060600160405280610d4d612a0c565b6001600160a01b0316632f04d7986040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061449b565b8152602001610dbb612a32565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1c919061449b565b8152602001610e29612a3d565b6001600160a01b03166344936b106040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8a919061449b565b905290506000610e98612857565b60408051606081019091529091506000906005600383835b82821015610f0757604080516060810182528386015463ffffffff811682526001600160701b03600160201b82048116602080850191909152600160901b9092041692820192909252825260019092019101610eb0565b5050505090506000806000610f1d858742610a41565b925092509250610f2f858588426112ef565b935060005b600381101561107857848160038110610f4f57610f4f6144fa565b602002015160058260038110610f6757610f676144fa565b825191018054602084015160409094015163ffffffff9093166001600160901b031990911617600160201b6001600160701b0394851602176001600160901b0316600160901b93909216929092021790557f398b51c40083342613440c91c6ec440c0944beb5d27769ea6cc90efe16cca34d60058260038110610fec57610fec6144fa565b015463ffffffff1660058360038110611007576110076144fa565b0154600160201b90046001600160701b03166005846003811061102c5761102c6144fa565b01546040805163ffffffff90941684526001600160701b039283166020850152600160901b9091049091169082015260600160405180910390a18061107081614510565b915050610f34565b5061108283613195565b81156110aa576040518281526000805160206145cf8339815191529060200160405180910390a15b80156110d2576040518181526000805160206145af8339815191529060200160405180910390a15b6110e78385886000015189602001514261112a565b965050505050505090565b6005816003811061110257600080fd5b015463ffffffff811691506001600160701b03600160201b8204811691600160901b90041683565b6000806111368361328c565b90506000866003611148846001614529565b6111529190614552565b60038110611162576111626144fa565b60200201519050600087836003811061117d5761117d6144fa565b6020020151895160408b01519192506000916111a190670de0b6b3a7640000614566565b6111ab919061457d565b905060008a602001518b60400151670de0b6b3a76400006111cc9190614566565b6111d6919061457d565b9050600080856000015163ffffffff168903905060008187602001518760200151036001600160701b03168161120e5761120e61453c565b04905060008288604001518860400151036001600160701b0316816112355761123561453c565b049050600061124483886132ad565b9050600061125283886132c5565b90508d8f670de0b6b3a7640000028161126d5761126d61453c565b049101039350600092508b915061128e90508c6729a2241af62c0000614566565b611298919061457d565b9050600060648b6112b28e6801e5b8fa8fe2ac0000614566565b6112bc919061457d565b6112c6919061457d565b90506112db6112d584846132ad565b826132c5565b985050505050505050505b95945050505050565b6112f7613f5c565b6000611306836203f4806132d4565b9050600086905060008661131d8960a0015161328c565b6003811061132d5761132d6144fa565b6020020151905061133c613f5c565b60006113496002866144ca565b90505b84811161149557600061136b886113666203f48085614566565b6132ad565b9050600061137a600384614552565b90508560a0015182116114265760405180606001604052808c83600381106113a4576113a46144fa565b60200201516000015163ffffffff1681526020018c83600381106113ca576113ca6144fa565b6020020151602001516001600160701b031681526020018c83600381106113f3576113f36144fa565b6020020151604001516001600160701b03169052848260038110611419576114196144fa565b6020020152506114839050565b6000611433878c85610a41565b5050905061144c8782888e600001518f60200151612212565b85836003811061145e5761145e6144fa565b6020020152955085848260038110611478576114786144fa565b602002015195505050505b8061148d81614510565b91505061134c565b5093505050505b949350505050565b60008054906101000a90046001600160a01b03166001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151991906144dd565b6001600160a01b0316336001600160a01b03161461157e5760405162461bcd60e51b815260206004820152601d60248201527f43616c6c6572206973206e6f7420656d657267656e63792061646d696e00000060448201526064015b60405180910390fd5b611587826132f7565b6008600c6101000a81548163ffffffff021916908363ffffffff1602179055506115b0816132f7565b6008601c6101000a81548163ffffffff021916908363ffffffff1602179055505050565b600054604051632c1a733d60e11b81523360048201526001600160a01b0390911690635834e67a90602401602060405180830381865afa15801561161c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116409190614591565b6116975760405162461bcd60e51b815260206004820152602260248201527f43616c6c6572206973206e6f7420617574686f72697a656420746f20676f7665604482015261393760f11b6064820152608401611575565b600480546affffffffffffffffffffff60801b191690556040517f2ca46d19fadde10b652ba2cceb5540c374dd95ed6c3799a78846066c044b294190600090a1565b60008054906101000a90046001600160a01b03166001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561172a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174e91906144dd565b6001600160a01b0316336001600160a01b0316146117ae5760405162461bcd60e51b815260206004820152601d60248201527f43616c6c6572206973206e6f7420656d657267656e63792061646d696e0000006044820152606401611575565b60048054821515600160f81b026001600160f81b039091161790556040517f55c7b3ec166bc5f2c12cbc5052f03ed7ce65c9cf9ab2af20484352f6a4a740a0906117fd90831515815260200190565b60405180910390a150565b600454600160d81b900463ffffffff16156118715760405162461bcd60e51b815260206004820152602360248201527f446973706f7361626c6552616d6d3a20416c726561647920696e697469616c696044820152621e995960ea1b6064820152608401611575565b6009839055600a829055600b81905560016020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f8054306001600160a01b031991821681179092557fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49805482168317905560036000527f7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b8054909116909117905561191b612d82565b5050600480546001600160f81b0316905550565b6000611939612857565b9050428160a00151036119495750565b6000604051806060016040528061195e612a0c565b6001600160a01b0316632f04d7986040518163ffffffff1660e01b8152600401602060405180830381865afa15801561199b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bf919061449b565b81526020016119cc612a32565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2d919061449b565b8152602001611a3a612a3d565b6001600160a01b03166344936b106040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9b919061449b565b905260408051606081019091529091506000906005600383835b82821015611b0c57604080516060810182528386015463ffffffff811682526001600160701b03600160201b82048116602080850191909152600160901b9092041692820192909252825260019092019101611ab5565b5050505090506000806000611b22868642610a41565b925092509250611b34868587426112ef565b935060005b6003811015611c7d57848160038110611b5457611b546144fa565b602002015160058260038110611b6c57611b6c6144fa565b825191018054602084015160409094015163ffffffff9093166001600160901b031990911617600160201b6001600160701b0394851602176001600160901b0316600160901b93909216929092021790557f398b51c40083342613440c91c6ec440c0944beb5d27769ea6cc90efe16cca34d60058260038110611bf157611bf16144fa565b015463ffffffff1660058360038110611c0c57611c0c6144fa565b0154600160201b90046001600160701b031660058460038110611c3157611c316144fa565b01546040805163ffffffff90941684526001600160701b039283166020850152600160901b9091049091169082015260600160405180910390a180611c7581614510565b915050611b39565b50611c8783613195565b8115611caf576040518281526000805160206145cf8339815191529060200160405180910390a15b8015611cd7576040518181526000805160206145af8339815191529060200160405180910390a15b505050505050565b600454600090600160801b90046001600160581b031615611d01575061138890565b5061019090565b60006002805403611d5b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611575565b600280553415801590611d6e5750600084115b15611d8c576040516349f67f3160e11b815260040160405180910390fd5b34158015611d98575083155b15611db65760405163d695701160e01b815260040160405180910390fd5b81421115611de0576040516327132a1d60e11b815260048101839052426024820152604401611575565b60006040518060600160405280611df5612a0c565b6001600160a01b0316632f04d7986040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e56919061449b565b8152602001611e63612a32565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ea0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec4919061449b565b8152602001611ed1612a3d565b6001600160a01b03166344936b106040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f32919061449b565b905290506000611f40612857565b905060008054906101000a90046001600160a01b03166001600160a01b031663ff0938a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb79190614591565b15611fd5576040516301ca793160e61b815260040160405180910390fd5b600454600160f81b900460ff16156120005760405163026d6c1b60e11b815260040160405180910390fd5b600080341161201a576120158787858561335f565b612026565b612026348785856136f8565b905034156120f85760085461205590612050908390600160801b90046001600160601b0316614529565b613a62565b600880546001600160601b0392909216600160801b026bffffffffffffffffffffffff60801b19909216919091179081905563ffffffff600160e01b90910416158015906120d557506008546120c090600160e01b900463ffffffff16670de0b6b3a7640000614566565b600854600160801b90046001600160601b0316115b156120f35760405163c1ea2d8f60e01b815260040160405180910390fd5b61219e565b600854612113906120509083906001600160601b0316614529565b600880546bffffffffffffffffffffffff19166001600160601b03929092169190911790819055600160601b900463ffffffff1615801590612180575060085461217290600160601b900463ffffffff16670de0b6b3a7640000614566565b6008546001600160601b0316115b1561219e5760405163ca765dab60e01b815260040160405180910390fd5b6121a6612a3d565b604051631b2622ff60e11b8152600060048201526001600160a01b03919091169063364c45fe90602401600060405180830381600087803b1580156121ea57600080fd5b505af11580156121fe573d6000803e3d6000fd5b505060016002555090979650505050505050565b604080516060810182526000808252602082018190529181019190915260008660a001518660a0015161224591906144ca565b9050600061225888888488886001613ac6565b9050600061226b89898589896000613ac6565b905060405180606001604052806122858a60a001516132f7565b63ffffffff16815260200188602001516001600160701b0316846122a99190614529565b6001600160701b0316815260200188604001516001600160701b0316836122d09190614529565b6001600160701b031690529998505050505050505050565b6122f0613f5c565b60008080612301856203f4806132d4565b905060006203f480612314600b846144ca565b61231e9190614566565b9050600061232d6002846144ca565b90505b8281116123ff57600061234a886113666203f48085614566565b90506000612359600384614552565b9050600061236785846144ca565b9050612373818d614566565b61237d9089614529565b9750612389818c614566565b6123939088614529565b965060405180606001604052806123a9856132f7565b63ffffffff168152602001896001600160701b03168152602001886001600160701b03168152508983600381106123e2576123e26144fa565b6020020152509092508190506123f781614510565b915050612330565b50505050509392505050565b6000546001600160a01b031615612463576000546001600160a01b031633146124635760405162461bcd60e51b815260206004820152600a6024820152692737ba1036b0b9ba32b960b11b6044820152606401611575565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806000604051806060016040528061249d612a0c565b6001600160a01b0316632f04d7986040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fe919061449b565b815260200161250b612a32565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612548573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256c919061449b565b8152602001612579612a3d565b6001600160a01b03166344936b106040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125da919061449b565b9052905060006125eb610a16612857565b5050805160408201519192509061260a90670de0b6b3a7640000614566565b612614919061457d565b6020820151604083015161263090670de0b6b3a7640000614566565b61263a919061457d565b9350935050509091565b600080604051806060016040528061265a612a0c565b6001600160a01b0316632f04d7986040518163ffffffff1660e01b8152600401602060405180830381865afa158015612697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126bb919061449b565b81526020016126c8612a32565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612705573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612729919061449b565b8152602001612736612a3d565b6001600160a01b03166344936b106040518163ffffffff1660e01b8152600401602060405180830381865afa158015612773573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612797919061449b565b9052905060006127a5612857565b60408051606081019091529091506000906005600383835b8282101561281457604080516060810182528386015463ffffffff811682526001600160701b03600160201b82048116602080850191909152600160901b90920416928201929092528252600190920191016127bd565b5050505090506000612827838542610a41565b50509050612837838386426112ef565b915061284e8183866000015187602001514261112a565b94505050505090565b6128906040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805160c0810182526003546001600160801b038082168352600160801b9182900481166020840152600454908116938301939093529091046001600160581b0316606082018190526080820190156128ec576113886128f0565b6101905b8152600454600160d81b900463ffffffff16602090910152919050565b600080612918612a0c565b6001600160a01b0316632f04d7986040518163ffffffff1660e01b8152600401602060405180830381865afa158015612955573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612979919061449b565b90506000612985612a32565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e6919061449b565b9050806129fb83670de0b6b3a7640000614566565b612a05919061457d565b9250505090565b6000600181815b81526020810191909152604001600020546001600160a01b0316919050565b600060018180612a13565b60006001816003612a13565b60008060008069010f0cf064dd59200000881015612a9a57612a6d88888888613c17565b9150612a798289614529565b9750818711612a89576000612a93565b612a9382886144ca565b9650612ae1565b612ad262015180612ab468056bc75e2d6310000088614566565b612abe919061457d565b61136669010f0cf064dd592000008b6144ca565b9050612ade81896144ca565b97505b96979596909590945092505050565b60008082612b02578660200151612b05565b86515b9050600087604001518783612b1a9190614566565b612b24919061457d565b9050600084612b3f57612b3a60646127106144ca565b612b4c565b612b4c6064612710614529565b90506000612710828860000151612b639190614566565b612b6d919061457d565b90508515612c75576020870151612b84908a614566565b612710620151806101908b612b998887614566565b612ba39190614566565b612bad9190614566565b612bb7919061457d565b612bc1919061457d565b612bcb8584614566565b612bd59190614529565b11612c4f576127106201518088602001516101908b878c60000151612bfa9190614566565b612c049190614566565b612c0e9190614566565b612c18919061457d565b612c22919061457d565b612c2c919061457d565b612c36908a6144ca565b612c40848b614566565b612c4a919061457d565b612c6a565b8087602001518a612c609190614566565b612c6a919061457d565b9450505050506112e6565b612710620151808b608001518a868b60000151612c929190614566565b612c9c9190614566565b612ca69190614566565b612cb0919061457d565b612cba919061457d565b6020880151612cc9908b614566565b612cd39190614529565b612cdd8483614566565b10612d59576127106201518088602001518c608001518b878c60000151612d049190614566565b612d0e9190614566565b612d189190614566565b612d22919061457d565b612d2c919061457d565b612d36919061457d565b612d40908a614529565b612d4a848b614566565b612d54919061457d565b612d74565b8087602001518a612d6a9190614566565b612d74919061457d565b9a9950505050505050505050565b600454600160d81b900463ffffffff1615612d9957565b6000612da3612a0c565b6001600160a01b0316632f04d7986040518163ffffffff1660e01b8152600401602060405180830381865afa158015612de0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e04919061449b565b90506000612e10612a32565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e71919061449b565b90506000612e7d612a0c565b6001600160a01b0316634b94f50e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ede919061449b565b90506000826127106064612efa87670de0b6b3a7640000614566565b612f049190614566565b612f0e919061457d565b612f18919061457d565b612f229083614529565b9050600083612710612f356064826144ca565b612f4788670de0b6b3a7640000614566565b612f519190614566565b612f5b919061457d565b612f65919061457d565b90506000612f9883612f8969010f0cf064dd59200000670de0b6b3a7640000614566565b612f93919061457d565b613d50565b90506000612fdc7f0000000000000000000000000000000000000000000000000096fd865af44000612f8969010f0cf064dd59200000670de0b6b3a7640000614566565b90506000612ff369010f0cf064dd59200000613d50565b9050600061300a6909484cd41c37600c0000613db5565b9050611388600061301a426132f7565b90506130276155f06132f7565b6008600c6101000a81548163ffffffff021916908363ffffffff1602179055506130536203d0906132f7565b6008805463ffffffff928316600160e01b026001600160e01b03909116179055600480546001600160f81b0316600160f81b1790556040805160c0810182526001600160801b03808a16825288811660208301528716918101919091526001600160581b03851660608201526080810184905290821660a08201526130d781613195565b60006130ea8a8a8563ffffffff166122e8565b905060005b60038110156131855781816003811061310a5761310a6144fa565b602002015160058260038110613122576131226144fa565b825191018054602084015160409094015163ffffffff9093166001600160901b031990911617600160201b6001600160701b0394851602176001600160901b0316600160901b93909216929092021790558061317d81614510565b9150506130ef565b5050505050505050505050505050565b80516131a090613d50565b600380546001600160801b0319166001600160801b039290921691909117905560208101516131ce90613d50565b600380546001600160801b03928316600160801b02921691909117905560408101516131f990613d50565b600480546001600160801b0319166001600160801b0392909216919091179055606081015161322790613db5565b600480546001600160581b0392909216600160801b026affffffffffffffffffffff60801b1990921691909117905560a0810151613264906132f7565b6004805463ffffffff92909216600160d81b0263ffffffff60d81b1990921691909117905550565b6000600361329d836203f4806132d4565b6132a79190614552565b92915050565b60008183106132bc57816132be565b825b9392505050565b60008183116132bc57816132be565b60008160016132e38286614529565b6132ed91906144ca565b6132be919061457d565b6000600160201b821061335b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401611575565b5090565b604080516060810190915260009081906005600383835b828210156133cd57604080516060810182528386015463ffffffff811682526001600160701b03600160201b82048116602080850191909152600160901b9092041692820192909252825260019092019101613376565b50505050905060008060006133e3868842610a41565b9250925092506133f5868589426112ef565b935060008360200151846040015161340d9190614566565b905060008a85602001516134219190614529565b9050600061342f828461457d565b9050600086604001518288600001516134489190614566565b613452919061457d565b905081876040015161346491906144ca565b98508b8910156134915760405163126c3c7360e21b8152600481018a9052602481018d9052604401611575565b60408b01518b516134a3908b906144ca565b10156134c2576040516359426e8360e11b815260040160405180910390fd5b865260208601919091526040850152504260a08401526134e183613195565b8115613509576040518281526000805160206145cf8339815191529060200160405180910390a15b8015613531576040518181526000805160206145af8339815191529060200160405180910390a15b60005b60038110156135ca5784816003811061354f5761354f6144fa565b602002015160058260038110613567576135676144fa565b825191018054602084015160409094015163ffffffff9093166001600160901b031990911617600160201b6001600160701b0394851602176001600160901b0316600160901b9390921692909202179055806135c281614510565b915050613534565b506135d3612a32565b60405163079cc67960e41b8152336004820152602481018b90526001600160a01b0391909116906379cc6790906044016020604051808303816000875af1158015613622573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136469190614591565b5061364f612a0c565b6040516324ee5e2f60e11b8152336004820152602481018790526001600160a01b0391909116906349dcbc5e90604401600060405180830381600087803b15801561369957600080fd5b505af11580156136ad573d6000803e3d6000fd5b5050604080518c8152602081018990523393507f4dc7f7059e30a400ff6a542834c87dab3774e0a9ac02346b928bfc336f1f7bf392500160405180910390a250505050949350505050565b604080516060810190915260009081906005600383835b8282101561376657604080516060810182528386015463ffffffff811682526001600160701b03600160201b82048116602080850191909152600160901b909204169282019290925282526001909201910161370f565b505050509050600080600061377c868842610a41565b92509250925061378e868589426112ef565b93506000836000015184604001516137a69190614566565b905060008a85604001516137ba9190614529565b905060006137c8828461457d565b9050600086604001518388602001516137e19190614566565b6137eb919061457d565b87519091506137fb9083906144ca565b98508b8910156138285760405163126c3c7360e21b8152600481018a9052602481018d9052604401611575565b90865260208601526040850152504260a084015261384583613195565b811561386d576040518281526000805160206145cf8339815191529060200160405180910390a15b8015613895576040518181526000805160206145af8339815191529060200160405180910390a15b60005b600381101561392e578481600381106138b3576138b36144fa565b6020020151600582600381106138cb576138cb6144fa565b825191018054602084015160409094015163ffffffff9093166001600160901b031990911617600160201b6001600160701b0394851602176001600160901b0316600160901b93909216929092021790558061392681614510565b915050613898565b506000613939612a0c565b6001600160a01b03163460405160006040518083038185875af1925050503d8060008114613983576040519150601f19603f3d011682016040523d82523d6000602084013e613988565b606091505b50909150506001811515146139b057604051630db2c7f160e31b815260040160405180910390fd5b6139b8612a32565b6040516340c10f1960e01b8152336004820152602481018890526001600160a01b0391909116906340c10f1990604401600060405180830381600087803b158015613a0257600080fd5b505af1158015613a16573d6000803e3d6000fd5b5050604080518d8152602081018a90523393507f11db3d568555307b53f9e9d32403ae0f696e7bcbd25fb61788d32e064b49387c92500160405180910390a25050505050949350505050565b6000600160601b821061335b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b6064820152608401611575565b60008060009050600080613ae28a898b60800151898b8a613e19565b9150915081600014613b8f57600085613aff578a60200151613b02565b8a515b9050600086613b15578a60200151613b18565b8a515b9050613b248183614566565b613b2f906002614566565b84838d60400151613b409190614566565b838f60400151613b509190614566565b613b5a9190614529565b613b6c90670de0b6b3a7640000614566565b613b769190614566565b613b80919061457d565b613b8a9086614529565b945050505b8015613c0957600085613bae57613ba960646127106144ca565b613bbb565b613bbb6064612710614529565b9050613bc961271088614566565b8189613bdd85670de0b6b3a7640000614566565b613be79190614566565b613bf19190614566565b613bfb919061457d565b613c059085614529565b9350505b509098975050505050505050565b600080685150ae84a8cdf00000613c316201518087614566565b613c3b919061457d565b9050600069010f0cf064dd592000008560400151613c599190614529565b855111613c67576000613ca4565b613ca4613c7e8869010f0cf064dd592000006144ca565b6040870151875169010f0cf064dd5920000091613c9a916144ca565b61136691906144ca565b9050818411613ce057613cd762015180613cc7685150ae84a8cdf0000087614566565b613cd1919061457d565b826132ad565b9250505061149c565b600062015180613cf9685150ae84a8cdf0000085614566565b613d03919061457d565b905060006201518068056bc75e2d63100000613d1f86896144ca565b613d299190614566565b613d33919061457d565b9050613d43836113668385614529565b9998505050505050505050565b6000600160801b821061335b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401611575565b6000600160581b821061335b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203860448201526538206269747360d01b6064820152608401611575565b600080600083613e2d578860200151613e30565b88515b9050600084613e3f5787613e43565b6101905b9050600085613e5e57613e5960646127106144ca565b613e6b565b613e6b6064612710614529565b9050600080898d60400151613e809190614566565b9050600061271086613e928c87614566565b613e9c9190614566565b613ea6919061457d565b9050600089613eb55781613eb7565b825b905060008a613ec65783613ec8565b825b9050808211613ed8576000613ee2565b613ee281836144ca565b945050505050600081600003613ef9576000613f32565b83613f04868b614566565b613f0e9190614566565b62015180613f1e61271085614566565b613f289190614566565b613f32919061457d565b9050613f3e8c826132ad565b9650613f4a878d6144ca565b95505050505050965096945050505050565b60405180606001604052806003905b6040805160608101825260008082526020808301829052928201528252600019909201910181613f6b5790505090565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715613fd457613fd4613f9b565b60405290565b600060c08284031215613fec57600080fd5b60405160c0810181811067ffffffffffffffff8211171561400f5761400f613f9b565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a08201525092915050565b60006060828403121561406657600080fd5b61406e613fb1565b905081358152602082013560208201526040820135604082015292915050565b600080600061014084860312156140a457600080fd5b6140ae8585613fda565b92506140bd8560c08601614054565b915061012084013590509250925092565b61010081016141128286805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b60c082019390935260e00152919050565b60006020828403121561413557600080fd5b5035919050565b80356001600160701b038116811461415357600080fd5b919050565b60006060828403121561416a57600080fd5b614172613fb1565b9050813563ffffffff8116811461418857600080fd5b81526141966020830161413c565b60208201526141a76040830161413c565b604082015292915050565b600082601f8301126141c357600080fd5b6141cb613fb1565b806101208401858111156141de57600080fd5b845b81811015614202576141f28782614158565b84526020909301926060016141e0565b509095945050505050565b6000806000806000610240868803121561422657600080fd5b6142308787613fda565b945061423f8760c088016141b2565b94979496505050506101e08301359261020081013592610220909101359150565b600080600080610260858703121561427757600080fd5b6142818686613fda565b93506142908660c087016141b2565b92506142a0866101e08701614054565b939692955092936102400135925050565b6101208101818360005b600381101561430e576142f8838351805163ffffffff1682526020808201516001600160701b039081169184019190915260409182015116910152565b60609290920191602091909101906001016142bb565b50505092915050565b6000806040838503121561432a57600080fd5b50508035926020909101359150565b801515811461434757600080fd5b50565b60006020828403121561435c57600080fd5b81356132be81614339565b60008060006060848603121561437c57600080fd5b505081359360208301359350604090920135919050565b600080600080600061022086880312156143ac57600080fd5b6143b68787613fda565b94506143c58760c08801613fda565b93506143d5876101808801614158565b949793965093946101e08101359450610200013592915050565b606081016132a78284805163ffffffff1682526020808201516001600160701b039081169184019190915260409182015116910152565b6001600160a01b038116811461434757600080fd5b60006020828403121561444d57600080fd5b81356132be81614426565b60c081016132a78284805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b6000602082840312156144ad57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156132a7576132a76144b4565b6000602082840312156144ef57600080fd5b81516132be81614426565b634e487b7160e01b600052603260045260246000fd5b600060018201614522576145226144b4565b5060010190565b808201808211156132a7576132a76144b4565b634e487b7160e01b600052601260045260246000fd5b6000826145615761456161453c565b500690565b80820281158282048414176132a7576132a76144b4565b60008261458c5761458c61453c565b500490565b6000602082840312156145a357600080fd5b81516132be8161433956fe77dcabf770d7a83dccad1ada406e9f6803698e89a0366ffd861ea37f8b0c62b60c34fd976d4acba944a797150ed7a2bbb31bae33aaeced825ee7680972b594e4a26469706673582212209b44b47a3c6e9e835da7b2f7de350d99f5bb3511b003ac59a174c43c91aafcbf64736f6c63430008120033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.