Source Code
Overview
HYPE Balance
HYPE Value
$0.00Latest 25 from a total of 118 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Fee Of Pair | 24357843 | 14 days ago | IN | 0 HYPE | 0.00023695 | ||||
| Set Fee Of Pair | 24357782 | 14 days ago | IN | 0 HYPE | 0.00001578 | ||||
| Set Lambda Of Pa... | 24027162 | 18 days ago | IN | 0 HYPE | 0.00000495 | ||||
| Set K Of Pair | 24026796 | 18 days ago | IN | 0 HYPE | 0.0000085 | ||||
| Set Lambda Of Pa... | 24009106 | 18 days ago | IN | 0 HYPE | 0.00000678 | ||||
| Set K Of Pair | 24009045 | 18 days ago | IN | 0 HYPE | 0.00000545 | ||||
| Set Lambda Of Pa... | 24008984 | 18 days ago | IN | 0 HYPE | 0.00000495 | ||||
| Set K Of Pair | 24008923 | 18 days ago | IN | 0 HYPE | 0.00000611 | ||||
| Set Lambda Of Pa... | 24008862 | 18 days ago | IN | 0 HYPE | 0.00001153 | ||||
| Set K Of Pair | 24008740 | 18 days ago | IN | 0 HYPE | 0.0000059 | ||||
| Set Fee Of Pair | 23939749 | 19 days ago | IN | 0 HYPE | 0.0000055 | ||||
| Set Lambda Of Pa... | 22485470 | 36 days ago | IN | 0 HYPE | 0.00000525 | ||||
| Set K Of Pair | 22485348 | 36 days ago | IN | 0 HYPE | 0.00000618 | ||||
| Set Fee Of Pair | 22328848 | 37 days ago | IN | 0 HYPE | 0.00001101 | ||||
| Set Lambda Of Pa... | 22328787 | 37 days ago | IN | 0 HYPE | 0.00000718 | ||||
| Set K Of Pair | 22328665 | 37 days ago | IN | 0 HYPE | 0.00000491 | ||||
| Set Fee Of Pair | 22220085 | 39 days ago | IN | 0 HYPE | 0.00000557 | ||||
| Set Fee Of Pair | 21448069 | 47 days ago | IN | 0 HYPE | 0.00001578 | ||||
| Set Protocol Fee... | 21447947 | 47 days ago | IN | 0 HYPE | 0.00002714 | ||||
| Set Protocol Fee... | 21447886 | 47 days ago | IN | 0 HYPE | 0.0000059 | ||||
| Set Protocol Fee... | 21447764 | 47 days ago | IN | 0 HYPE | 0.00000491 | ||||
| Set Protocol Fee... | 21447703 | 47 days ago | IN | 0 HYPE | 0.00000491 | ||||
| Set Protocol Fee... | 20992544 | 53 days ago | IN | 0 HYPE | 0.00000885 | ||||
| Set Protocol Fee... | 20992361 | 53 days ago | IN | 0 HYPE | 0.00000491 | ||||
| Set Protocol Fee... | 20992300 | 53 days ago | IN | 0 HYPE | 0.00000491 |
Latest 6 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 20464610 | 59 days ago | Contract Creation | 0 HYPE | |||
| 20464000 | 59 days ago | Contract Creation | 0 HYPE | |||
| 20462231 | 59 days ago | Contract Creation | 0 HYPE | |||
| 12845266 | 145 days ago | Contract Creation | 0 HYPE | |||
| 8798716 | 191 days ago | Contract Creation | 0 HYPE | |||
| 8798655 | 191 days ago | Contract Creation | 0 HYPE |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
BrownFiV2Factory
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 999999 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.28;
import './interfaces/IPriceOracle.sol';
import './interfaces/IBrownFiV2Factory.sol';
import './BrownFiV2Pair.sol';
import '@openzeppelin/contracts/access/manager/AccessManaged.sol';
contract BrownFiV2Factory is IBrownFiV2Factory, AccessManaged {
address public priceOracle;
address public feeTo;
bool public paused;
uint public constant Q64 = 1 << 64;
uint public minPriceAge;
// token address -> price feed id
mapping(address => bytes32) public priceFeedIds;
mapping(address => mapping(address => address)) public getPair;
address[] public allPairs;
modifier checkPairExists(address tokenA, address tokenB) {
require(getPair[tokenA][tokenB] != address(0), 'BrownFiV2: PAIR_NOT_EXISTS');
_;
}
constructor(address _initialOracle, address _initialManager) AccessManaged(_initialManager) {
priceOracle = _initialOracle;
minPriceAge = 15; // default to 15 seconds
}
function setPriceOracle(address _newOracle) external restricted {
priceOracle = _newOracle;
}
// Add pause/unpause functions
function setPaused(bool _paused) external restricted {
paused = _paused;
emit PauseStateChanged(_paused);
}
// Check if operations are paused
function isPaused() external view returns (bool) {
return paused;
}
function priceOf(address token, uint priceAge) external view returns(uint _price) {
return IPriceOracle(priceOracle).getPrice(priceFeedIds[token], priceAge);
}
function allPairsLength() external view returns (uint) {
return allPairs.length;
}
function createPair(address tokenA, address tokenB, bytes32 priceFeedA, bytes32 priceFeedB) external returns (address pair) {
if(!_hasOracle(tokenA)) {
_setOracleOf(tokenA, priceFeedA);
}
if(!_hasOracle(tokenB)) {
_setOracleOf(tokenB, priceFeedB);
}
// re-check oracle
require(_hasOracle(tokenA), "BrownFiV2: ORACLE_A_REQUIRED");
require(_hasOracle(tokenB), "BrownFiV2: ORACLE_B_REQUIRED");
require(tokenA != tokenB, 'BrownFiV2: IDENTICAL_ADDRESSES');
(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), 'BrownFiV2: ZERO_ADDRESS');
require(getPair[token0][token1] == address(0), 'BrownFiV2: PAIR_EXISTS'); // single check is sufficient
bytes memory bytecode = type(BrownFiV2Pair).creationCode;
bytes32 salt = keccak256(abi.encodePacked(token0, token1));
assembly {
pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
}
IBrownFiV2Pair(pair).initialize(token0, token1);
getPair[token0][token1] = pair;
getPair[token1][token0] = pair; // populate mapping in the reverse direction
allPairs.push(pair);
emit PairCreated(token0, token1, pair, allPairs.length);
}
function setFeeTo(address _feeTo) external restricted() {
feeTo = _feeTo;
}
function setOracleOf(address token, bytes32 feedId) external restricted {
_setOracleOf(token, feedId);
emit OracleOfUpdated(token, feedId);
}
function setMinPriceAge(uint age) external restricted {
minPriceAge = age;
emit MinPriceAgeUpdated(age);
}
function setKOfPair(address tokenA, address tokenB, uint k) external checkPairExists(tokenA, tokenB) restricted {
address pair = getPair[tokenA][tokenB];
IBrownFiV2Pair(pair).setK(k);
emit KOfPairUpdated(tokenA, tokenB, k);
}
function setFeeOfPair(address tokenA, address tokenB, uint32 fee) external checkPairExists(tokenA, tokenB) restricted {
require(fee <= 10_000_000, "BrownFiV2: FEE_TOO_HIGH");
address pair = getPair[tokenA][tokenB];
IBrownFiV2Pair(pair).setFee(fee);
emit FeeOfPairUpdated(tokenA, tokenB, fee);
}
function setLambdaOfPair(address tokenA, address tokenB, uint64 lambda) external checkPairExists(tokenA, tokenB) restricted {
address pair = getPair[tokenA][tokenB];
IBrownFiV2Pair(pair).setLambda(lambda);
emit LambdaOfPairUpdated(tokenA, tokenB, lambda);
}
function setProtocolFeeOfPair(address tokenA, address tokenB, uint32 protocolFee) external checkPairExists(tokenA, tokenB) restricted {
require(protocolFee <= 80_000_000, "BrownFiV2: PROTOCOL_FEE_TOO_HIGH");
address pair = getPair[tokenA][tokenB];
IBrownFiV2Pair(pair).setProtocolFee(protocolFee);
emit ProtocolFeeOfPairUpdated(tokenA, tokenB, protocolFee);
}
function _setOracleOf(address token, bytes32 feedId) private {
if(token == address(0) || feedId == "") return;
priceFeedIds[token] = feedId;
}
function _hasOracle(address token) private view returns(bool) {
return priceFeedIds[token] != "";
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/manager/AccessManaged.sol)
pragma solidity ^0.8.20;
import {IAuthority} from "./IAuthority.sol";
import {AuthorityUtils} from "./AuthorityUtils.sol";
import {IAccessManager} from "./IAccessManager.sol";
import {IAccessManaged} from "./IAccessManaged.sol";
import {Context} from "../../utils/Context.sol";
/**
* @dev This contract module makes available a {restricted} modifier. Functions decorated with this modifier will be
* permissioned according to an "authority": a contract like {AccessManager} that follows the {IAuthority} interface,
* implementing a policy that allows certain callers to access certain functions.
*
* IMPORTANT: The `restricted` modifier should never be used on `internal` functions, judiciously used in `public`
* functions, and ideally only used in `external` functions. See {restricted}.
*/
abstract contract AccessManaged is Context, IAccessManaged {
address private _authority;
bool private _consumingSchedule;
/**
* @dev Initializes the contract connected to an initial authority.
*/
constructor(address initialAuthority) {
_setAuthority(initialAuthority);
}
/**
* @dev Restricts access to a function as defined by the connected Authority for this contract and the
* caller and selector of the function that entered the contract.
*
* [IMPORTANT]
* ====
* In general, this modifier should only be used on `external` functions. It is okay to use it on `public`
* functions that are used as external entry points and are not called internally. Unless you know what you're
* doing, it should never be used on `internal` functions. Failure to follow these rules can have critical security
* implications! This is because the permissions are determined by the function that entered the contract, i.e. the
* function at the bottom of the call stack, and not the function where the modifier is visible in the source code.
* ====
*
* [WARNING]
* ====
* Avoid adding this modifier to the https://docs.soliditylang.org/en/v0.8.20/contracts.html#receive-ether-function[`receive()`]
* function or the https://docs.soliditylang.org/en/v0.8.20/contracts.html#fallback-function[`fallback()`]. These
* functions are the only execution paths where a function selector cannot be unambiguously determined from the calldata
* since the selector defaults to `0x00000000` in the `receive()` function and similarly in the `fallback()` function
* if no calldata is provided. (See {_checkCanCall}).
*
* The `receive()` function will always panic whereas the `fallback()` may panic depending on the calldata length.
* ====
*/
modifier restricted() {
_checkCanCall(_msgSender(), _msgData());
_;
}
/// @inheritdoc IAccessManaged
function authority() public view virtual returns (address) {
return _authority;
}
/// @inheritdoc IAccessManaged
function setAuthority(address newAuthority) public virtual {
address caller = _msgSender();
if (caller != authority()) {
revert AccessManagedUnauthorized(caller);
}
if (newAuthority.code.length == 0) {
revert AccessManagedInvalidAuthority(newAuthority);
}
_setAuthority(newAuthority);
}
/// @inheritdoc IAccessManaged
function isConsumingScheduledOp() public view returns (bytes4) {
return _consumingSchedule ? this.isConsumingScheduledOp.selector : bytes4(0);
}
/**
* @dev Transfers control to a new authority. Internal function with no access restriction. Allows bypassing the
* permissions set by the current authority.
*/
function _setAuthority(address newAuthority) internal virtual {
_authority = newAuthority;
emit AuthorityUpdated(newAuthority);
}
/**
* @dev Reverts if the caller is not allowed to call the function identified by a selector. Panics if the calldata
* is less than 4 bytes long.
*/
function _checkCanCall(address caller, bytes calldata data) internal virtual {
(bool immediate, uint32 delay) = AuthorityUtils.canCallWithDelay(
authority(),
caller,
address(this),
bytes4(data[0:4])
);
if (!immediate) {
if (delay > 0) {
_consumingSchedule = true;
IAccessManager(authority()).consumeScheduledOp(caller, data);
_consumingSchedule = false;
} else {
revert AccessManagedUnauthorized(caller);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/manager/AuthorityUtils.sol)
pragma solidity ^0.8.20;
import {IAuthority} from "./IAuthority.sol";
library AuthorityUtils {
/**
* @dev Since `AccessManager` implements an extended IAuthority interface, invoking `canCall` with backwards compatibility
* for the preexisting `IAuthority` interface requires special care to avoid reverting on insufficient return data.
* This helper function takes care of invoking `canCall` in a backwards compatible way without reverting.
*/
function canCallWithDelay(
address authority,
address caller,
address target,
bytes4 selector
) internal view returns (bool immediate, uint32 delay) {
bytes memory data = abi.encodeCall(IAuthority.canCall, (caller, target, selector));
assembly ("memory-safe") {
mstore(0x00, 0x00)
mstore(0x20, 0x00)
if staticcall(gas(), authority, add(data, 0x20), mload(data), 0x00, 0x40) {
immediate := mload(0x00)
delay := mload(0x20)
// If delay does not fit in a uint32, return 0 (no delay)
// equivalent to: if gt(delay, 0xFFFFFFFF) { delay := 0 }
delay := mul(delay, iszero(shr(32, delay)))
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/IAccessManaged.sol)
pragma solidity ^0.8.20;
interface IAccessManaged {
/**
* @dev Authority that manages this contract was updated.
*/
event AuthorityUpdated(address authority);
error AccessManagedUnauthorized(address caller);
error AccessManagedRequiredDelay(address caller, uint32 delay);
error AccessManagedInvalidAuthority(address authority);
/**
* @dev Returns the current authority.
*/
function authority() external view returns (address);
/**
* @dev Transfers control to a new authority. The caller must be the current authority.
*/
function setAuthority(address) external;
/**
* @dev Returns true only in the context of a delayed restricted call, at the moment that the scheduled operation is
* being consumed. Prevents denial of service for delayed restricted calls in the case that the contract performs
* attacker controlled calls.
*/
function isConsumingScheduledOp() external view returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/manager/IAccessManager.sol)
pragma solidity ^0.8.20;
import {Time} from "../../utils/types/Time.sol";
interface IAccessManager {
/**
* @dev A delayed operation was scheduled.
*/
event OperationScheduled(
bytes32 indexed operationId,
uint32 indexed nonce,
uint48 schedule,
address caller,
address target,
bytes data
);
/**
* @dev A scheduled operation was executed.
*/
event OperationExecuted(bytes32 indexed operationId, uint32 indexed nonce);
/**
* @dev A scheduled operation was canceled.
*/
event OperationCanceled(bytes32 indexed operationId, uint32 indexed nonce);
/**
* @dev Informational labelling for a roleId.
*/
event RoleLabel(uint64 indexed roleId, string label);
/**
* @dev Emitted when `account` is granted `roleId`.
*
* NOTE: The meaning of the `since` argument depends on the `newMember` argument.
* If the role is granted to a new member, the `since` argument indicates when the account becomes a member of the role,
* otherwise it indicates the execution delay for this account and roleId is updated.
*/
event RoleGranted(uint64 indexed roleId, address indexed account, uint32 delay, uint48 since, bool newMember);
/**
* @dev Emitted when `account` membership or `roleId` is revoked. Unlike granting, revoking is instantaneous.
*/
event RoleRevoked(uint64 indexed roleId, address indexed account);
/**
* @dev Role acting as admin over a given `roleId` is updated.
*/
event RoleAdminChanged(uint64 indexed roleId, uint64 indexed admin);
/**
* @dev Role acting as guardian over a given `roleId` is updated.
*/
event RoleGuardianChanged(uint64 indexed roleId, uint64 indexed guardian);
/**
* @dev Grant delay for a given `roleId` will be updated to `delay` when `since` is reached.
*/
event RoleGrantDelayChanged(uint64 indexed roleId, uint32 delay, uint48 since);
/**
* @dev Target mode is updated (true = closed, false = open).
*/
event TargetClosed(address indexed target, bool closed);
/**
* @dev Role required to invoke `selector` on `target` is updated to `roleId`.
*/
event TargetFunctionRoleUpdated(address indexed target, bytes4 selector, uint64 indexed roleId);
/**
* @dev Admin delay for a given `target` will be updated to `delay` when `since` is reached.
*/
event TargetAdminDelayUpdated(address indexed target, uint32 delay, uint48 since);
error AccessManagerAlreadyScheduled(bytes32 operationId);
error AccessManagerNotScheduled(bytes32 operationId);
error AccessManagerNotReady(bytes32 operationId);
error AccessManagerExpired(bytes32 operationId);
error AccessManagerLockedRole(uint64 roleId);
error AccessManagerBadConfirmation();
error AccessManagerUnauthorizedAccount(address msgsender, uint64 roleId);
error AccessManagerUnauthorizedCall(address caller, address target, bytes4 selector);
error AccessManagerUnauthorizedConsume(address target);
error AccessManagerUnauthorizedCancel(address msgsender, address caller, address target, bytes4 selector);
error AccessManagerInvalidInitialAdmin(address initialAdmin);
/**
* @dev Check if an address (`caller`) is authorised to call a given function on a given contract directly (with
* no restriction). Additionally, it returns the delay needed to perform the call indirectly through the {schedule}
* & {execute} workflow.
*
* This function is usually called by the targeted contract to control immediate execution of restricted functions.
* Therefore we only return true if the call can be performed without any delay. If the call is subject to a
* previously set delay (not zero), then the function should return false and the caller should schedule the operation
* for future execution.
*
* If `immediate` is true, the delay can be disregarded and the operation can be immediately executed, otherwise
* the operation can be executed if and only if delay is greater than 0.
*
* NOTE: The IAuthority interface does not include the `uint32` delay. This is an extension of that interface that
* is backward compatible. Some contracts may thus ignore the second return argument. In that case they will fail
* to identify the indirect workflow, and will consider calls that require a delay to be forbidden.
*
* NOTE: This function does not report the permissions of the admin functions in the manager itself. These are defined by the
* {AccessManager} documentation.
*/
function canCall(
address caller,
address target,
bytes4 selector
) external view returns (bool allowed, uint32 delay);
/**
* @dev Expiration delay for scheduled proposals. Defaults to 1 week.
*
* IMPORTANT: Avoid overriding the expiration with 0. Otherwise every contract proposal will be expired immediately,
* disabling any scheduling usage.
*/
function expiration() external view returns (uint32);
/**
* @dev Minimum setback for all delay updates, with the exception of execution delays. It
* can be increased without setback (and reset via {revokeRole} in the case event of an
* accidental increase). Defaults to 5 days.
*/
function minSetback() external view returns (uint32);
/**
* @dev Get whether the contract is closed disabling any access. Otherwise role permissions are applied.
*
* NOTE: When the manager itself is closed, admin functions are still accessible to avoid locking the contract.
*/
function isTargetClosed(address target) external view returns (bool);
/**
* @dev Get the role required to call a function.
*/
function getTargetFunctionRole(address target, bytes4 selector) external view returns (uint64);
/**
* @dev Get the admin delay for a target contract. Changes to contract configuration are subject to this delay.
*/
function getTargetAdminDelay(address target) external view returns (uint32);
/**
* @dev Get the id of the role that acts as an admin for the given role.
*
* The admin permission is required to grant the role, revoke the role and update the execution delay to execute
* an operation that is restricted to this role.
*/
function getRoleAdmin(uint64 roleId) external view returns (uint64);
/**
* @dev Get the role that acts as a guardian for a given role.
*
* The guardian permission allows canceling operations that have been scheduled under the role.
*/
function getRoleGuardian(uint64 roleId) external view returns (uint64);
/**
* @dev Get the role current grant delay.
*
* Its value may change at any point without an event emitted following a call to {setGrantDelay}.
* Changes to this value, including effect timepoint are notified in advance by the {RoleGrantDelayChanged} event.
*/
function getRoleGrantDelay(uint64 roleId) external view returns (uint32);
/**
* @dev Get the access details for a given account for a given role. These details include the timepoint at which
* membership becomes active, and the delay applied to all operation by this user that requires this permission
* level.
*
* Returns:
* [0] Timestamp at which the account membership becomes valid. 0 means role is not granted.
* [1] Current execution delay for the account.
* [2] Pending execution delay for the account.
* [3] Timestamp at which the pending execution delay will become active. 0 means no delay update is scheduled.
*/
function getAccess(
uint64 roleId,
address account
) external view returns (uint48 since, uint32 currentDelay, uint32 pendingDelay, uint48 effect);
/**
* @dev Check if a given account currently has the permission level corresponding to a given role. Note that this
* permission might be associated with an execution delay. {getAccess} can provide more details.
*/
function hasRole(uint64 roleId, address account) external view returns (bool isMember, uint32 executionDelay);
/**
* @dev Give a label to a role, for improved role discoverability by UIs.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {RoleLabel} event.
*/
function labelRole(uint64 roleId, string calldata label) external;
/**
* @dev Add `account` to `roleId`, or change its execution delay.
*
* This gives the account the authorization to call any function that is restricted to this role. An optional
* execution delay (in seconds) can be set. If that delay is non 0, the user is required to schedule any operation
* that is restricted to members of this role. The user will only be able to execute the operation after the delay has
* passed, before it has expired. During this period, admin and guardians can cancel the operation (see {cancel}).
*
* If the account has already been granted this role, the execution delay will be updated. This update is not
* immediate and follows the delay rules. For example, if a user currently has a delay of 3 hours, and this is
* called to reduce that delay to 1 hour, the new delay will take some time to take effect, enforcing that any
* operation executed in the 3 hours that follows this update was indeed scheduled before this update.
*
* Requirements:
*
* - the caller must be an admin for the role (see {getRoleAdmin})
* - granted role must not be the `PUBLIC_ROLE`
*
* Emits a {RoleGranted} event.
*/
function grantRole(uint64 roleId, address account, uint32 executionDelay) external;
/**
* @dev Remove an account from a role, with immediate effect. If the account does not have the role, this call has
* no effect.
*
* Requirements:
*
* - the caller must be an admin for the role (see {getRoleAdmin})
* - revoked role must not be the `PUBLIC_ROLE`
*
* Emits a {RoleRevoked} event if the account had the role.
*/
function revokeRole(uint64 roleId, address account) external;
/**
* @dev Renounce role permissions for the calling account with immediate effect. If the sender is not in
* the role this call has no effect.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* Emits a {RoleRevoked} event if the account had the role.
*/
function renounceRole(uint64 roleId, address callerConfirmation) external;
/**
* @dev Change admin role for a given role.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {RoleAdminChanged} event
*/
function setRoleAdmin(uint64 roleId, uint64 admin) external;
/**
* @dev Change guardian role for a given role.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {RoleGuardianChanged} event
*/
function setRoleGuardian(uint64 roleId, uint64 guardian) external;
/**
* @dev Update the delay for granting a `roleId`.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {RoleGrantDelayChanged} event.
*/
function setGrantDelay(uint64 roleId, uint32 newDelay) external;
/**
* @dev Set the role required to call functions identified by the `selectors` in the `target` contract.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {TargetFunctionRoleUpdated} event per selector.
*/
function setTargetFunctionRole(address target, bytes4[] calldata selectors, uint64 roleId) external;
/**
* @dev Set the delay for changing the configuration of a given target contract.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {TargetAdminDelayUpdated} event.
*/
function setTargetAdminDelay(address target, uint32 newDelay) external;
/**
* @dev Set the closed flag for a contract.
*
* Closing the manager itself won't disable access to admin methods to avoid locking the contract.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {TargetClosed} event.
*/
function setTargetClosed(address target, bool closed) external;
/**
* @dev Return the timepoint at which a scheduled operation will be ready for execution. This returns 0 if the
* operation is not yet scheduled, has expired, was executed, or was canceled.
*/
function getSchedule(bytes32 id) external view returns (uint48);
/**
* @dev Return the nonce for the latest scheduled operation with a given id. Returns 0 if the operation has never
* been scheduled.
*/
function getNonce(bytes32 id) external view returns (uint32);
/**
* @dev Schedule a delayed operation for future execution, and return the operation identifier. It is possible to
* choose the timestamp at which the operation becomes executable as long as it satisfies the execution delays
* required for the caller. The special value zero will automatically set the earliest possible time.
*
* Returns the `operationId` that was scheduled. Since this value is a hash of the parameters, it can reoccur when
* the same parameters are used; if this is relevant, the returned `nonce` can be used to uniquely identify this
* scheduled operation from other occurrences of the same `operationId` in invocations of {execute} and {cancel}.
*
* Emits a {OperationScheduled} event.
*
* NOTE: It is not possible to concurrently schedule more than one operation with the same `target` and `data`. If
* this is necessary, a random byte can be appended to `data` to act as a salt that will be ignored by the target
* contract if it is using standard Solidity ABI encoding.
*/
function schedule(
address target,
bytes calldata data,
uint48 when
) external returns (bytes32 operationId, uint32 nonce);
/**
* @dev Execute a function that is delay restricted, provided it was properly scheduled beforehand, or the
* execution delay is 0.
*
* Returns the nonce that identifies the previously scheduled operation that is executed, or 0 if the
* operation wasn't previously scheduled (if the caller doesn't have an execution delay).
*
* Emits an {OperationExecuted} event only if the call was scheduled and delayed.
*/
function execute(address target, bytes calldata data) external payable returns (uint32);
/**
* @dev Cancel a scheduled (delayed) operation. Returns the nonce that identifies the previously scheduled
* operation that is cancelled.
*
* Requirements:
*
* - the caller must be the proposer, a guardian of the targeted function, or a global admin
*
* Emits a {OperationCanceled} event.
*/
function cancel(address caller, address target, bytes calldata data) external returns (uint32);
/**
* @dev Consume a scheduled operation targeting the caller. If such an operation exists, mark it as consumed
* (emit an {OperationExecuted} event and clean the state). Otherwise, throw an error.
*
* This is useful for contract that want to enforce that calls targeting them were scheduled on the manager,
* with all the verifications that it implies.
*
* Emit a {OperationExecuted} event.
*/
function consumeScheduledOp(address caller, bytes calldata data) external;
/**
* @dev Hashing function for delayed operations.
*/
function hashOperation(address caller, address target, bytes calldata data) external view returns (bytes32);
/**
* @dev Changes the authority of a target managed by this manager instance.
*
* Requirements:
*
* - the caller must be a global admin
*/
function updateAuthority(address target, address newAuthority) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/IAuthority.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard interface for permissioning originally defined in Dappsys.
*/
interface IAuthority {
/**
* @dev Returns true if the caller can invoke on a target the function identified by a function selector.
*/
function canCall(address caller, address target, bytes4 selector) external view returns (bool allowed);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
import {Panic} from "../Panic.sol";
import {SafeCast} from "./SafeCast.sol";
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
*/
function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
assembly ("memory-safe") {
low := add(a, b)
high := lt(low, a)
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
*/
function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = high * 2²⁵⁶ + low.
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
low := mul(a, b)
high := sub(sub(mm, low), lt(mm, low))
}
}
/**
* @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
success = c >= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a - b;
success = c <= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a * b;
assembly ("memory-safe") {
// Only true when the multiplication doesn't overflow
// (c / a == b) || (a == 0)
success := or(eq(div(c, a), b), iszero(a))
}
// equivalent to: success ? c : 0
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `DIV` opcode returns zero when the denominator is 0.
result := div(a, b)
}
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `MOD` opcode returns zero when the denominator is 0.
result := mod(a, b)
}
}
}
/**
* @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryAdd(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
*/
function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
(, uint256 result) = trySub(a, b);
return result;
}
/**
* @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryMul(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (high == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return low / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= high) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [high low].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
high := sub(high, gt(remainder, low))
low := sub(low, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly ("memory-safe") {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [high low] by twos.
low := div(low, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from high into low.
low |= high * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
// is no longer required.
result = low * inverse;
return result;
}
}
/**
* @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
*/
function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
if (high >= 1 << n) {
Panic.panic(Panic.UNDER_OVERFLOW);
}
return (high << (256 - n)) | (low >> n);
}
}
/**
* @dev Calculates x * y >> n with full precision, following the selected rounding direction.
*/
function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;
// Shifts value right by the current result and use it as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
assembly ("memory-safe") {
r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
}
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 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 SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @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) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
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) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
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) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
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) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
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) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
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) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
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) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
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) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
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) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
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) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
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) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
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) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
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) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
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) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
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) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
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) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
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) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
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) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
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) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
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 `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
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 `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
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 `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(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) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
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) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
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) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
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) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
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) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
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) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
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) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
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) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* // Use any of the declared internal constants
* function foo() { Panic.GENERIC.panic(); }
*
* // Alternatively
* function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
*
* _Available since v5.1._
*/
// slither-disable-next-line unused-state
library Panic {
/// @dev generic / unspecified error
uint256 internal constant GENERIC = 0x00;
/// @dev used by the assert() builtin
uint256 internal constant ASSERT = 0x01;
/// @dev arithmetic underflow or overflow
uint256 internal constant UNDER_OVERFLOW = 0x11;
/// @dev division or modulo by zero
uint256 internal constant DIVISION_BY_ZERO = 0x12;
/// @dev enum conversion error
uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
/// @dev invalid encoding in storage
uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
/// @dev empty array pop
uint256 internal constant EMPTY_ARRAY_POP = 0x31;
/// @dev array out of bounds access
uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
/// @dev resource error (too large allocation or too large array)
uint256 internal constant RESOURCE_ERROR = 0x41;
/// @dev calling invalid internal function
uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
/// @dev Reverts with a panic code. Recommended to use with
/// the internal constants with predefined codes.
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/types/Time.sol)
pragma solidity ^0.8.20;
import {Math} from "../math/Math.sol";
import {SafeCast} from "../math/SafeCast.sol";
/**
* @dev This library provides helpers for manipulating time-related objects.
*
* It uses the following types:
* - `uint48` for timepoints
* - `uint32` for durations
*
* While the library doesn't provide specific types for timepoints and duration, it does provide:
* - a `Delay` type to represent duration that can be programmed to change value automatically at a given point
* - additional helper functions
*/
library Time {
using Time for *;
/**
* @dev Get the block timestamp as a Timepoint.
*/
function timestamp() internal view returns (uint48) {
return SafeCast.toUint48(block.timestamp);
}
/**
* @dev Get the block number as a Timepoint.
*/
function blockNumber() internal view returns (uint48) {
return SafeCast.toUint48(block.number);
}
// ==================================================== Delay =====================================================
/**
* @dev A `Delay` is a uint32 duration that can be programmed to change value automatically at a given point in the
* future. The "effect" timepoint describes when the transitions happens from the "old" value to the "new" value.
* This allows updating the delay applied to some operation while keeping some guarantees.
*
* In particular, the {update} function guarantees that if the delay is reduced, the old delay still applies for
* some time. For example if the delay is currently 7 days to do an upgrade, the admin should not be able to set
* the delay to 0 and upgrade immediately. If the admin wants to reduce the delay, the old delay (7 days) should
* still apply for some time.
*
*
* The `Delay` type is 112 bits long, and packs the following:
*
* ```
* | [uint48]: effect date (timepoint)
* | | [uint32]: value before (duration)
* ↓ ↓ ↓ [uint32]: value after (duration)
* 0xAAAAAAAAAAAABBBBBBBBCCCCCCCC
* ```
*
* NOTE: The {get} and {withUpdate} functions operate using timestamps. Block number based delays are not currently
* supported.
*/
type Delay is uint112;
/**
* @dev Wrap a duration into a Delay to add the one-step "update in the future" feature
*/
function toDelay(uint32 duration) internal pure returns (Delay) {
return Delay.wrap(duration);
}
/**
* @dev Get the value at a given timepoint plus the pending value and effect timepoint if there is a scheduled
* change after this timepoint. If the effect timepoint is 0, then the pending value should not be considered.
*/
function _getFullAt(
Delay self,
uint48 timepoint
) private pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) {
(valueBefore, valueAfter, effect) = self.unpack();
return effect <= timepoint ? (valueAfter, 0, 0) : (valueBefore, valueAfter, effect);
}
/**
* @dev Get the current value plus the pending value and effect timepoint if there is a scheduled change. If the
* effect timepoint is 0, then the pending value should not be considered.
*/
function getFull(Delay self) internal view returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) {
return _getFullAt(self, timestamp());
}
/**
* @dev Get the current value.
*/
function get(Delay self) internal view returns (uint32) {
(uint32 delay, , ) = self.getFull();
return delay;
}
/**
* @dev Update a Delay object so that it takes a new duration after a timepoint that is automatically computed to
* enforce the old delay at the moment of the update. Returns the updated Delay object and the timestamp when the
* new delay becomes effective.
*/
function withUpdate(
Delay self,
uint32 newValue,
uint32 minSetback
) internal view returns (Delay updatedDelay, uint48 effect) {
uint32 value = self.get();
uint32 setback = uint32(Math.max(minSetback, value > newValue ? value - newValue : 0));
effect = timestamp() + setback;
return (pack(value, newValue, effect), effect);
}
/**
* @dev Split a delay into its components: valueBefore, valueAfter and effect (transition timepoint).
*/
function unpack(Delay self) internal pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) {
uint112 raw = Delay.unwrap(self);
valueAfter = uint32(raw);
valueBefore = uint32(raw >> 32);
effect = uint48(raw >> 64);
return (valueBefore, valueAfter, effect);
}
/**
* @dev pack the components into a Delay object.
*/
function pack(uint32 valueBefore, uint32 valueAfter, uint48 effect) internal pure returns (Delay) {
return Delay.wrap((uint112(effect) << 64) | (uint112(valueBefore) << 32) | uint112(valueAfter));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
function mulDiv(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = a * b
// Compute the product mod 2**256 and mod 2**256 - 1
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2**256 + prod0
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(a, b, not(0))
prod0 := mul(a, b)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division
if (prod1 == 0) {
require(denominator > 0);
assembly {
result := div(prod0, denominator)
}
return result;
}
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0]
// Compute remainder using mulmod
uint256 remainder;
assembly {
remainder := mulmod(a, b, denominator)
}
// Subtract 256 bit number from 512 bit number
assembly {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator
// Compute largest power of two divisor of denominator.
// Always >= 1.
uint256 twos = (0 - denominator) & denominator;
// Divide denominator by power of two
assembly {
denominator := div(denominator, twos)
}
// Divide [prod1 prod0] by the factors of two
assembly {
prod0 := div(prod0, twos)
}
// Shift in bits from prod1 into prod0. For this we need
// to flip `twos` such that it is 2**256 / twos.
// If twos is zero, then it becomes one
assembly {
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
// Invert denominator mod 2**256
// Now that denominator is an odd number, it has an inverse
// modulo 2**256 such that denominator * inv = 1 mod 2**256.
// Compute the inverse by starting with a seed that is correct
// correct for four bits. That is, denominator * inv = 1 mod 2**4
uint256 inv = (3 * denominator) ^ 2;
// Now use Newton-Raphson iteration to improve the precision.
// Thanks to Hensel's lifting lemma, this also works in modular
// arithmetic, doubling the correct bits in each step.
inv *= 2 - denominator * inv; // inverse mod 2**8
inv *= 2 - denominator * inv; // inverse mod 2**16
inv *= 2 - denominator * inv; // inverse mod 2**32
inv *= 2 - denominator * inv; // inverse mod 2**64
inv *= 2 - denominator * inv; // inverse mod 2**128
inv *= 2 - denominator * inv; // inverse mod 2**256
// Because the division is now exact we can divide by multiplying
// with the modular inverse of denominator. This will give us the
// correct result modulo 2**256. Since the precoditions guarantee
// that the outcome is less than 2**256, this is the final result.
// We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inv;
return result;
}
}
/// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
function mulDivRoundingUp(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) > 0) {
require(result < type(uint256).max);
result++;
}
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.28;
import './interfaces/IBrownFiV2ERC20.sol';
import './libraries/SafeMath.sol';
contract BrownFiV2ERC20 is IBrownFiV2ERC20 {
using SafeMath for uint;
string public constant override name = 'BrownFi V2';
string public constant override symbol = 'BF-V2';
uint8 public constant override decimals = 18;
uint public override totalSupply;
mapping(address => uint) public override balanceOf;
mapping(address => mapping(address => uint)) public override allowance;
bytes32 public override DOMAIN_SEPARATOR;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant override PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint) public override nonces;
constructor() {
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
keccak256(bytes(name)),
keccak256(bytes('1')),
block.chainid,
address(this)
)
);
}
function _mint(address to, uint value) internal {
totalSupply = totalSupply.add(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(address(0), to, value);
}
function _burn(address from, uint value) internal {
balanceOf[from] = balanceOf[from].sub(value);
totalSupply = totalSupply.sub(value);
emit Transfer(from, address(0), value);
}
function _approve(address owner, address spender, uint value) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _transfer(address from, address to, uint value) private {
balanceOf[from] = balanceOf[from].sub(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(from, to, value);
}
function approve(address spender, uint value) external override returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transfer(address to, uint value) external override returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint value) external override returns (bool) {
if (allowance[from][msg.sender] != type(uint256).max) {
allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
}
_transfer(from, to, value);
return true;
}
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external override {
require(deadline >= block.timestamp, 'BrownFiV2: EXPIRED');
bytes32 digest = keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
require(recoveredAddress != address(0) && recoveredAddress == owner, 'BrownFiV2: INVALID_SIGNATURE');
_approve(owner, spender, value);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.28;
import './interfaces/IBrownFiV2Pair.sol';
import './BrownFiV2ERC20.sol';
import './libraries/Math.sol';
import '@uniswap/v3-core/contracts/libraries/FullMath.sol';
import './libraries/UQ112x112.sol';
import './interfaces/IERC20.sol';
import './interfaces/IBrownFiV2Factory.sol';
import './interfaces/IBrownFiV2Callee.sol';
contract BrownFiV2Pair is IBrownFiV2Pair, BrownFiV2ERC20 {
using SafeMath for uint;
using UQ112x112 for uint224;
uint public constant override MINIMUM_LIQUIDITY = 10**3;
uint32 public constant PRECISION = 10**8;
uint public constant Q64 = 1 << 64;
address public immutable override factory;
address public override token0;
uint8 public token0Decimals;
address public override token1;
uint8 public token1Decimals;
uint112 private reserve0; // uses single storage slot, accessible via getReserves
uint112 private reserve1; // uses single storage slot, accessible via getReserves
uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves
bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
uint public override k = uint(Q64) / 1000; // default 0.001
uint64 public override lambda = 0; // default 0
uint32 public override fee = 300_000; // default 0.3%
uint64 public protocolFee = 10_000_000; // default 10%
uint private unlocked = 1;
modifier lock() {
require(unlocked == 1, 'BrownFiV2: LOCKED');
unlocked = 0;
_;
unlocked = 1;
}
modifier whenNotPaused() {
require(!IBrownFiV2Factory(factory).isPaused(), "BrownFiV2: PAUSED");
_;
}
modifier onlyFactory() {
require(msg.sender == factory, 'BrownFiV2: ONLY_FACTORY');
_;
}
function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
_reserve0 = reserve0;
_reserve1 = reserve1;
_blockTimestampLast = blockTimestampLast;
}
function _safeTransfer(address token, address to, uint value) private {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'BrownFiV2: TRANSFER_FAILED');
}
constructor() {
factory = msg.sender;
}
// called once by the factory at time of deployment
function initialize(address _token0, address _token1) external {
require(msg.sender == factory, 'BrownFiV2: FORBIDDEN'); // sufficient check
require(_token0 != address(0) && _token1 != address(0), 'BrownFiV2: ZERO_ADDRESS');
token0 = _token0;
token1 = _token1;
token0Decimals = IERC20(_token0).decimals();
token1Decimals = IERC20(_token1).decimals();
}
function _getPrices() internal view returns (uint price0, uint price1) {
uint minPriceAge = IBrownFiV2Factory(factory).minPriceAge();
price0 = IBrownFiV2Factory(factory).priceOf(token0, minPriceAge);
price1 = IBrownFiV2Factory(factory).priceOf(token1, minPriceAge);
}
/**
* @dev convert raw amount to default decimals amount
*/
function _parseAmountToDefaultDecimals(uint8 tokenDecimals, uint amount) internal pure returns (uint formattedAmount) {
formattedAmount = tokenDecimals > decimals ?
amount / 10**uint(tokenDecimals - decimals) : amount * 10**uint(decimals - tokenDecimals);
}
// update reserves and, on the first call per block, price accumulators
function _update(uint balance0, uint balance1) private {
require(balance0 <= type(uint112).max && balance1 <= type(uint112).max, 'BrownFiV2: OVERFLOW');
uint32 blockTimestamp = uint32(block.timestamp % 2**32);
reserve0 = uint112(balance0);
reserve1 = uint112(balance1);
blockTimestampLast = blockTimestamp;
emit Sync(reserve0, reserve1);
}
// this low-level function should be called from a contract which performs important safety checks
function mint(address to) external lock whenNotPaused returns (uint liquidity) {
(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
uint balance0 = IERC20(token0).balanceOf(address(this));
uint balance1 = IERC20(token1).balanceOf(address(this));
uint amount0 = balance0.sub(_reserve0);
uint amount1 = balance1.sub(_reserve1);
(uint price0, uint price1) = _getPrices();
uint parsedAmount0 = _parseAmountToDefaultDecimals(token0Decimals, amount0);
uint parsedAmount1 = _parseAmountToDefaultDecimals(token1Decimals, amount1);
uint minValue = Math.min(parsedAmount0.mul(price0), parsedAmount1.mul(price1));
uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
if (_totalSupply == 0) {
liquidity = minValue.mul(2) / Q64 - MINIMUM_LIQUIDITY;
_mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
} else {
uint parsedReserve0 = _parseAmountToDefaultDecimals(token0Decimals, _reserve0);
uint parsedReserve1 = _parseAmountToDefaultDecimals(token1Decimals, _reserve1);
liquidity = FullMath.mulDiv(
_totalSupply,
minValue.mul(2),
price0.mul(parsedReserve0).add(
price1.mul(parsedReserve1)
)
);
}
require(liquidity > 0, 'BrownFiV2: INSUFFICIENT_LIQUIDITY_MINTED');
_mint(to, liquidity);
_update(balance0, balance1);
emit Mint(msg.sender, amount0, amount1, price0, price1, to);
}
// this low-level function should be called from a contract which performs important safety checks
function burn(address to) external lock whenNotPaused returns (uint amount0, uint amount1) {
address _token0 = token0; // gas savings
address _token1 = token1; // gas savings
uint balance0 = IERC20(_token0).balanceOf(address(this));
uint balance1 = IERC20(_token1).balanceOf(address(this));
uint liquidity = balanceOf[address(this)];
// bool feeOn = _mintFee(_reserve0, _reserve1);
uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution
amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution
require(amount0 > 0 && amount1 > 0, 'BrownFiV2: INSUFFICIENT_LIQUIDITY_BURNED');
_burn(address(this), liquidity);
_safeTransfer(_token0, to, amount0);
_safeTransfer(_token1, to, amount1);
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
_update(balance0, balance1);
emit Burn(msg.sender, amount0, amount1, to);
}
// this low-level function should be called from a contract which performs important safety checks
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock whenNotPaused {
require(amount0Out > 0 || amount1Out > 0, 'BrownFiV2: INSUFFICIENT_OUTPUT_AMOUNT');
(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
require(amount0Out.mul(10) <= uint(_reserve0).mul(8) && amount1Out.mul(10) <= uint(_reserve1).mul(8), 'BrownFiV2: INSUFFICIENT_LIQUIDITY');
uint balance0;
uint balance1;
{ // scope for _token{0,1}, avoids stack too deep errors
address _token0 = token0;
address _token1 = token1;
require(to != _token0 && to != _token1, 'BrownFiV2: INVALID_TO');
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
if (data.length > 0) IBrownFiV2Callee(to).brownFiV2Call(msg.sender, amount0Out, amount1Out, data);
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
}
uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
require(amount0In > 0 || amount1In > 0, 'BrownFiV2: INSUFFICIENT_INPUT_AMOUNT');
{ // scope for reserve{0,1}Adjusted, avoids stack too deep errors
(uint price0, uint price1) = _getPrices();
(uint sPrice0, uint sPrice1) = (price0, price1);
if (lambda > 0) {
(sPrice0, sPrice1) = computeSkewnessPrice(_reserve0, _reserve1, price0, price1);
}
uint amount0OutWithoutFee = FullMath.mulDiv(amount0Out, PRECISION, PRECISION + fee);
uint amount1OutWithoutFee = FullMath.mulDiv(amount1Out, PRECISION, PRECISION + fee);
// check inventory
if (amount0Out > 0) {
checkInventory(balance0, balance1, sPrice0, sPrice1, amount0OutWithoutFee, false);
}
if (amount1Out > 0) {
checkInventory(balance0, balance1, sPrice0, sPrice1, amount1OutWithoutFee, true);
}
_update(balance0, balance1);
// calculate protocol fee
if(protocolFee > 0) {
uint lpForProtocol;
uint _totalSupply = totalSupply;
uint inventoryRight = computeInventoryRight(price0, price1);
if (amount0In > 0) {
uint _amount0In = _parseAmountToDefaultDecimals(token0Decimals, amount0In);
uint tradingFee = FullMath.mulDiv(_amount0In, fee, PRECISION + fee);
uint protocolFeeInDollarValue = FullMath.mulDiv(tradingFee, protocolFee * price0, PRECISION);
lpForProtocol = FullMath.mulDiv(protocolFeeInDollarValue, _totalSupply, inventoryRight);
}
if (amount1In > 0) {
uint _amount1In = _parseAmountToDefaultDecimals(token1Decimals, amount1In);
uint tradingFee = FullMath.mulDiv(_amount1In, fee, PRECISION + fee);
uint protocolFeeInDollarValue = FullMath.mulDiv(tradingFee, protocolFee * price1, PRECISION);
lpForProtocol = FullMath.mulDiv(protocolFeeInDollarValue, _totalSupply, inventoryRight);
}
if (lpForProtocol > 0) {
_mint(IBrownFiV2Factory(factory).feeTo(), lpForProtocol);
}
}
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, sPrice0, sPrice1, to);
}
}
function computeSkewnessPrice(uint _reserve0, uint _reserve1, uint _price0, uint _price1) internal view returns (uint, uint) {
uint _r0 = _parseAmountToDefaultDecimals(token0Decimals, _reserve0);
uint _r1 = _parseAmountToDefaultDecimals(token1Decimals, _reserve1);
// s = lambda * |x * px - y * py| / (x * px + y * py)
uint reserve0Price = _r0 * _price0;
uint reserve1Price = _r1 * _price1;
uint reservePriceDiff = reserve0Price >= reserve1Price ?
reserve0Price - reserve1Price :
reserve1Price - reserve0Price;
uint reservePriceSum = reserve0Price + reserve1Price;
uint s = FullMath.mulDiv(reservePriceDiff, lambda, reservePriceSum);
uint q64PlusS = Q64 + s;
uint q64MinusS = Q64 - s;
// if x * px >= y * py, px = px * (1 - s), py = py * (1 + s)
// if x * px <= y * py, px = px * (1 + s), py = py * (1 - s)
if (reserve0Price >= reserve1Price) {
return (
FullMath.mulDiv(_price0, q64MinusS, Q64),
FullMath.mulDiv(_price1, q64PlusS, Q64)
);
} else {
return (
FullMath.mulDiv(_price0, q64PlusS, Q64),
FullMath.mulDiv(_price1, q64MinusS, Q64)
);
}
}
function checkInventory(uint balance0, uint balance1, uint price0, uint price1, uint amountOut, bool zeroToOne) internal view {
uint _balance0 = _parseAmountToDefaultDecimals(token0Decimals, balance0);
uint _balance1 = _parseAmountToDefaultDecimals(token1Decimals, balance1);
uint _amountOut = _parseAmountToDefaultDecimals(zeroToOne ? token1Decimals : token0Decimals, amountOut);
uint left = computeInventoryLeft(_balance0, _balance1, price0, price1, _amountOut, zeroToOne);
uint right = computeInventoryRight(price0, price1);
require(left >= right, 'BrownFiV2: INVALID_INVENTORY');
}
function computeInventoryLeft(uint balance0, uint balance1, uint price0, uint price1, uint amountOut, bool zeroToOne) internal view returns (uint) {
uint _k = k;
uint balance = zeroToOne ? balance1 : balance0;
uint price = zeroToOne ? price1 : price0;
// Pre-calculate the denominator with one multiplication
uint denominator = balance.mul(Q64).mul(2);
return price0.mul(balance0).add(price1.mul(balance1)).sub(
FullMath.mulDiv(
price.mul(_k),
amountOut.mul(amountOut),
denominator
)
);
}
function computeInventoryRight(
uint price0,
uint price1
) internal view returns (uint) {
(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
uint _r0 = _parseAmountToDefaultDecimals(token0Decimals, _reserve0);
uint _r1 = _parseAmountToDefaultDecimals(token1Decimals, _reserve1);
return price0.mul(_r0).add(price1.mul(_r1));
}
// force balances to match reserves
function skim(address to) external lock {
}
// force reserves to match balances
function sync() external lock {
_update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)));
}
function setK(uint _k) external onlyFactory {
require(_k <= 2 * Q64, 'BrownFiV2: MAXIMUM_K');
k = _k;
}
function setLambda(uint64 _lambda) external onlyFactory {
require(_lambda <= Q64, 'BrownFiV2: MAXIMUM_LAMBDA'); // max 1
lambda = _lambda;
}
function setFee(uint32 _fee) external onlyFactory {
fee = _fee;
}
function setProtocolFee(uint32 _protocolFee) external onlyFactory {
protocolFee = _protocolFee;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;
interface IBrownFiV2Callee {
function brownFiV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;
interface IBrownFiV2ERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;
interface IBrownFiV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint totalPair);
event PauseStateChanged(bool paused);
event PriceOracleUpdated(address indexed newOracle);
event FeeToUpdated(address indexed newFeeTo);
event OracleOfUpdated(address indexed token, bytes32 priceFeedId);
event MinPriceAgeUpdated(uint newMinPriceAge);
event KOfPairUpdated(address indexed tokenA, address indexed tokenB, uint k);
event FeeOfPairUpdated(address indexed tokenA, address indexed tokenB, uint32 fee);
event LambdaOfPairUpdated(address indexed tokenA, address indexed tokenB, uint64 lambda);
event ProtocolFeeOfPairUpdated(address indexed tokenA, address indexed tokenB, uint32 protocolFee);
function priceOracle() external view returns (address);
function feeTo() external view returns (address);
function priceOf(address token, uint256 priceAge) external view returns(uint256);
function minPriceAge() external view returns (uint);
function priceFeedIds(address token) external view returns (bytes32);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB, bytes32 priceFeedA, bytes32 priceFeedB) external returns (address pair);
function setPriceOracle(address newOracle) external;
function setFeeTo(address) external;
function setOracleOf(address token, bytes32 priceFeedId) external;
function setMinPriceAge(uint age) external;
function setKOfPair(address tokenA, address tokenB, uint k) external;
function setFeeOfPair(address tokenA, address tokenB, uint32 fee) external;
function setLambdaOfPair(address tokenA, address tokenB, uint64 lambda) external;
function setProtocolFeeOfPair(address tokenA, address tokenB, uint32 protocolFee) external;
function setPaused(bool paused) external;
function isPaused() external view returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;
interface IBrownFiV2Pair {
event Mint(address indexed sender, uint amount0, uint amount1, uint price0, uint price1, address indexed to);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
uint price0,
uint price1,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function k() external view returns (uint);
function lambda() external view returns (uint64);
function fee() external view returns (uint32);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function setK(uint _k) external;
function setFee(uint32 _fee) external;
function setLambda(uint64 _lambda) external;
function setProtocolFee(uint32 _protocolFee) external;
function initialize(address, address) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.28;
interface IPriceOracle {
function pythContract() external view returns (address);
// Get price in Q64 format with a maximum age constraint
function getPrice(bytes32 feedId, uint priceAge) external view returns (uint price);
// Check if a feed is valid and exists
function isFeedValid(bytes32 feedId) external view returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.28;
// a library for performing various math operations
library Math {
function min(uint x, uint y) internal pure returns (uint z) {
z = x < y ? x : y;
}
// babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.28;
// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
library SafeMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.28;
// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
// range: [0, 2**112 - 1]
// resolution: 1 / 2**112
library UQ112x112 {
uint224 constant Q112 = 2**112;
// encode a uint112 as a UQ112x112
function encode(uint112 y) internal pure returns (uint224 z) {
z = uint224(y) * Q112; // never overflows
}
// divide a UQ112x112 by a uint112, returning a UQ112x112
function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
z = x / uint224(y);
}
}{
"optimizer": {
"enabled": true,
"runs": 999999
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_initialOracle","type":"address"},{"internalType":"address","name":"_initialManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"authority","type":"address"}],"name":"AccessManagedInvalidAuthority","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"uint32","name":"delay","type":"uint32"}],"name":"AccessManagedRequiredDelay","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"AccessManagedUnauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"authority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenA","type":"address"},{"indexed":true,"internalType":"address","name":"tokenB","type":"address"},{"indexed":false,"internalType":"uint32","name":"fee","type":"uint32"}],"name":"FeeOfPairUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newFeeTo","type":"address"}],"name":"FeeToUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenA","type":"address"},{"indexed":true,"internalType":"address","name":"tokenB","type":"address"},{"indexed":false,"internalType":"uint256","name":"k","type":"uint256"}],"name":"KOfPairUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenA","type":"address"},{"indexed":true,"internalType":"address","name":"tokenB","type":"address"},{"indexed":false,"internalType":"uint64","name":"lambda","type":"uint64"}],"name":"LambdaOfPairUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMinPriceAge","type":"uint256"}],"name":"MinPriceAgeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bytes32","name":"priceFeedId","type":"bytes32"}],"name":"OracleOfUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalPair","type":"uint256"}],"name":"PairCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"PauseStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOracle","type":"address"}],"name":"PriceOracleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenA","type":"address"},{"indexed":true,"internalType":"address","name":"tokenB","type":"address"},{"indexed":false,"internalType":"uint32","name":"protocolFee","type":"uint32"}],"name":"ProtocolFeeOfPairUpdated","type":"event"},{"inputs":[],"name":"Q64","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allPairsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"bytes32","name":"priceFeedA","type":"bytes32"},{"internalType":"bytes32","name":"priceFeedB","type":"bytes32"}],"name":"createPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getPair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isConsumingScheduledOp","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minPriceAge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"priceFeedIds","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"priceAge","type":"uint256"}],"name":"priceOf","outputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint32","name":"fee","type":"uint32"}],"name":"setFeeOfPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTo","type":"address"}],"name":"setFeeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"k","type":"uint256"}],"name":"setKOfPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint64","name":"lambda","type":"uint64"}],"name":"setLambdaOfPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"age","type":"uint256"}],"name":"setMinPriceAge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"feedId","type":"bytes32"}],"name":"setOracleOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOracle","type":"address"}],"name":"setPriceOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint32","name":"protocolFee","type":"uint32"}],"name":"setProtocolFeeOfPair","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60803460c457601f615be038819003918201601f19168301916001600160401b0383118484101760c957808492604094855283398101031260c4577f2f658b440c35314f52658ea8a740e05b284cdc84dc9ae01e891f21b8933e7cad602060648360df565b926001600160a01b0390607790830160df565b168060018060a01b03196000541617600055604051908152a1600180546001600160a01b0319166001600160a01b0392909216919091179055600f600355604051615aed90816100f38239f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b038216820360c45756fe6080604052600436101561001257600080fd5b60003560e01c8063017e7e581461019257806316c38b3c1461018d5780631e3dd18b146101885780632630c12f14610183578063336eb6ae1461017e57806333fca1871461017957806334667c1414610174578063530e784f1461016f578063574f2ba31461016a5780635c975abb1461014257806367cc34031461016557806378b2cd7d146101605780637a9e5e4b1461015b5780637e058f501461015657806388df8516146101515780638fb360371461014c578063b03b9f1f14610147578063b187bd2614610142578063bf7e214f1461013d578063cb3d74aa14610138578063e6a4390514610133578063e6bc07931461012e578063f46901ed146101295763fc3d545d1461012457600080fd5b611577565b6114f2565b611348565b6112b1565b6110e9565b611097565b6105a2565b610f4b565b610eb7565b610a67565b6109d5565b610897565b6106a1565b6105e6565b610566565b6104e1565b610475565b610433565b6103ce565b610336565b6102b1565b6101f9565b6101a7565b60009103126101a257565b600080fd5b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576004358015158091036101a25760207f4543baa938cb97f5073ec206ad35638cdb1f4db8f677d31579b2f6fe7d18c14a916102633633611bb4565b6002547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000008360a01b16911617600255604051908152a1005b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576004356006548110156101a25773ffffffffffffffffffffffffffffffffffffffff60209160066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f015416604051908152f35b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101a257565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036101a257565b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25773ffffffffffffffffffffffffffffffffffffffff61041a610388565b1660005260046020526020604060002054604051908152f35b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576020604051680100000000000000008152f35b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2577f4cce7b74bd7749107683fee0f1ad5547d2dcf7c7d893d93e20bdeadb1909395e60206004356104d43633611bb4565b80600355604051908152a1005b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25773ffffffffffffffffffffffffffffffffffffffff61052d610388565b6105373633611bb4565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006001541617600155600080f35b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576020600654604051908152f35b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602060ff60025460a01c166040519015158152f35b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576020600354604051908152f35b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60609101126101a25760043573ffffffffffffffffffffffffffffffffffffffff811681036101a2579060243573ffffffffffffffffffffffffffffffffffffffff811681036101a2579060443563ffffffff811681036101a25790565b346101a2576106af36610622565b91906107cf6107b66107b661079c8461077773ffffffffffffffffffffffffffffffffffffffff88169788600052600560205261073173ffffffffffffffffffffffffffffffffffffffff6107288560406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54161515611678565b61073b3633611bb4565b6107516304c4b40063ffffffff8c1611156116dd565b73ffffffffffffffffffffffffffffffffffffffff166000526005602052604060002090565b9073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b90813b156101a2576040517faa9f762800000000000000000000000000000000000000000000000000000000815263ffffffff85166004820152916000908390602490829084905af1908115610892577fe05b718c2e5d9ba7d193e3f618d623817996e0f922635158d409e31d00ee42c99273ffffffffffffffffffffffffffffffffffffffff92610877575b5060405163ffffffff9095168552169280602081015b0390a3005b80610886600061088c93611771565b80610197565b3861085c565b6117b7565b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576108ce610388565b6000549073ffffffffffffffffffffffffffffffffffffffff821633036109a757803b15610963577fffffffffffffffffffffffff00000000000000000000000000000000000000007f2f658b440c35314f52658ea8a740e05b284cdc84dc9ae01e891f21b8933e7cad9273ffffffffffffffffffffffffffffffffffffffff602093169182911617600055604051908152a1005b73ffffffffffffffffffffffffffffffffffffffff907fc2f31e5e000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b7f068ca9d8000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b346101a25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257610a0c610388565b7f35384503a4bc4d7d46a62b5e5973108c35f47b598b11199d085e8ce2b8043cdd602073ffffffffffffffffffffffffffffffffffffffff60243593610a523633611bb4565b610a5c8582611d4e565b6040519485521692a2005b346101a25760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257610a9e610388565b610aa66103ab565b9060443560643590610ae2610ade8473ffffffffffffffffffffffffffffffffffffffff166000526004602052604060002054151590565b1590565b610ea7575b50610b18610ade8473ffffffffffffffffffffffffffffffffffffffff166000526004602052604060002054151590565b610e97575b50610b53610b4e8273ffffffffffffffffffffffffffffffffffffffff166000526004602052604060002054151590565b6117c3565b610b88610b838373ffffffffffffffffffffffffffffffffffffffff166000526004602052604060002054151590565b611828565b73ffffffffffffffffffffffffffffffffffffffff821673ffffffffffffffffffffffffffffffffffffffff8216610bc28282141561188d565b1015610e9257905b73ffffffffffffffffffffffffffffffffffffffff821690610bed8215156118f2565b610c2a610c246107b661079c846107778873ffffffffffffffffffffffffffffffffffffffff166000526005602052604060002090565b15611957565b613c76610c39602082016119bc565b908082526020820190611e4282396040516020810190610cbf81610c93878a86906028927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000809260601b16835260601b1660148201520190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611771565b5190209151906000f59173ffffffffffffffffffffffffffffffffffffffff831693843b156101a2576040517f485cc95500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff828116600483015284166024820152946000908690604490829084905af194851561089257610d8d610df7928692610e7998610e7d575b50610dcd83610d8d886107778573ffffffffffffffffffffffffffffffffffffffff166000526005602052604060002090565b9073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b6107778673ffffffffffffffffffffffffffffffffffffffff166000526005602052604060002090565b610e00836119cc565b6006546040805173ffffffffffffffffffffffffffffffffffffffff8681168252602082019390935293909116927f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e99190a360405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b806108866000610e8c93611771565b38610d5a565b610bca565b610ea19083611d4e565b38610b1d565b610eb19083611d4e565b38610ae7565b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25760005460a01c60ff1615610f425760207f8fb36037000000000000000000000000000000000000000000000000000000005b7fffffffff0000000000000000000000000000000000000000000000000000000060405191168152f35b60206000610f18565b346101a257610f5936610622565b9190610ff16107b66107b661079c8461077773ffffffffffffffffffffffffffffffffffffffff881697886000526005602052610fd273ffffffffffffffffffffffffffffffffffffffff6107288560406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b610fdc3633611bb4565b6107516298968063ffffffff8c161115611a6a565b90813b156101a2576040517f1ab971ab00000000000000000000000000000000000000000000000000000000815263ffffffff85166004820152916000908390602490829084905af1908115610892577f6e1c36e9b395976f59344b51646e14ddbbdbdea13050432e2d6dfce4ebaced6c9273ffffffffffffffffffffffffffffffffffffffff92610877575060405163ffffffff909516855216928060208101610872565b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b346101a25760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257611120610388565b6111286103ab565b6044359167ffffffffffffffff831683036101a25773ffffffffffffffffffffffffffffffffffffffff16908160005260056020526111a373ffffffffffffffffffffffffffffffffffffffff6107288360406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b6111ad3633611bb4565b8160005260056020526111ed6107b66107b661079c8460406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b90813b156101a2576040517fcde5bf5300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152916000908390602490829084905af1908115610892577f675db29b8feddf09b6825fa7ae35928c772c56488772a384b474236449b4399e9273ffffffffffffffffffffffffffffffffffffffff9261129c575b5060405167ffffffffffffffff909516855216928060208101610872565b8061088660006112ab93611771565b3861127e565b346101a25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602073ffffffffffffffffffffffffffffffffffffffff61133e611302610388565b8261130b6103ab565b91166000526005845260406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5416604051908152f35b346101a25760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25761137f610388565b6113876103ab565b73ffffffffffffffffffffffffffffffffffffffff6044359216908160005260056020526113f173ffffffffffffffffffffffffffffffffffffffff6107288360406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b6113fb3633611bb4565b81600052600560205261143b6107b66107b661079c8460406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b90813b156101a257600060405180937f67de8be90000000000000000000000000000000000000000000000000000000082528183816114828a600483019190602083019252565b03925af1908115610892577f5424eaf93192b9cbb2ace7d1be43b65df9933b2f307857b698a3eb7f22a2fabb9273ffffffffffffffffffffffffffffffffffffffff926114dd575b5060405194855216928060208101610872565b8061088660006114ec93611771565b386114ca565b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25773ffffffffffffffffffffffffffffffffffffffff61153e610388565b6115483633611bb4565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255600080f35b346101a25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25761162260206115b3610388565b6024359073ffffffffffffffffffffffffffffffffffffffff80600154169116600052600483526040600020546040518095819482937fc9280f060000000000000000000000000000000000000000000000000000000084526004840160209093929193604081019481520152565b03915afa801561089257610e7991600091611649575b506040519081529081906020820190565b61166b915060203d602011611671575b6116638183611771565b810190611acf565b38611638565b503d611659565b1561167f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f42726f776e466956323a20504149525f4e4f545f4558495354530000000000006044820152fd5b156116e457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f42726f776e466956323a2050524f544f434f4c5f4645455f544f4f5f484947486044820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176117b257604052565b611742565b6040513d6000823e3d90fd5b156117ca57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f42726f776e466956323a204f5241434c455f415f5245515549524544000000006044820152fd5b1561182f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f42726f776e466956323a204f5241434c455f425f5245515549524544000000006044820152fd5b1561189457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f42726f776e466956323a204944454e544943414c5f41444452455353455300006044820152fd5b156118f957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f42726f776e466956323a205a45524f5f414444524553530000000000000000006044820152fd5b1561195e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f42726f776e466956323a20504149525f455849535453000000000000000000006044820152fd5b906119ca6040519283611771565b565b600654680100000000000000008110156117b257600181016006556000600654821015611a3d5790602082600673ffffffffffffffffffffffffffffffffffffffff9452200191167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526032600452fd5b15611a7157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f42726f776e466956323a204645455f544f4f5f484947480000000000000000006044820152fd5b908160209103126101a2575190565b906004116101a25790600490565b919091357fffffffff0000000000000000000000000000000000000000000000000000000081169260048110611b20575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b9183606094601f9273ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe095168652604060208701528160408701528686013760008582860101520116010190565b611bf3611bd660005473ffffffffffffffffffffffffffffffffffffffff1690565b611bea611be4856000611ade565b90611aec565b90833091611d8d565b9015611bfe57505050565b63ffffffff1615611d0b57611c4d740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff6000541617600055565b611c726107b66107b660005473ffffffffffffffffffffffffffffffffffffffff1690565b91823b156101a257611cb9926000808094604051968795869485937f94c7d7ee00000000000000000000000000000000000000000000000000000000855260048501611b52565b03925af1801561089257611cf6575b506119ca7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff60005416600055565b806108866000611d0593611771565b38611cc8565b7f068ca9d80000000000000000000000000000000000000000000000000000000060005273ffffffffffffffffffffffffffffffffffffffff1660045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff1680158015611d85575b611d81576000526004602052604060002055565b5050565b508115611d6d565b60009060409295939582967fffffffff00000000000000000000000000000000000000000000000000000000849773ffffffffffffffffffffffffffffffffffffffff8751938160208601967fb700961300000000000000000000000000000000000000000000000000000000885216602486015216604484015216606482015260648152611e1d608482611771565b8380528360205251915afa611e2e57565b915050600051906020518060201c15029056fe60a0604052346101555760405161001760408261015a565b600a815269213937bbb72334902b1960b11b602090910152604080517f6734371cf3152a7df61c4623a003b33fdd6df5cdf7648e19ad4b1d9eababb5159161005f908261015a565b600181526020810190603160f81b82525190206040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a081526100c360c08261015a565b519020600355664189374bc6a7ef600855600980546001600160a01b0319166e989680000493e000000000000000001790556001600a5533608052604051613ae2908161019482396080518181816107c6015281816108d601528181610ada01528181610c9c0152818161122e015281816116e4015281816117d701528181611d61015281816120a401526130e30152f35b600080fd5b601f909101601f19168101906001600160401b0382119082101761017d57604052565b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c8063022c0d9f14611fe357806306fdde0314611f6c5780630902f1ac14611edb578063095ea7b314611e965780630b77884d14611e545780630dfe168114611e0257806318160ddd14611dc75780631ab971ab14611d0757806323b872dd14611bdd57806330adf81f14611b84578063313ce56714611b4a57806333fca18714611b085780633644e51514611acc578063485cc9551461177f57806367de8be9146116975780636a627842146111a057806370a082311461113d5780637ecebe00146110da57806389afcb4414610c0f57806395d89b4114610b94578063a9059cbb14610b44578063aa9f762814610a80578063aaf5eb6814610a43578063b0e21e8a146109fa578063b31ac6e2146109b8578063b4f40c611461097c578063ba9a7a5614610941578063bc25cf77146108fa578063c45a01551461088b578063cde5bf5314610767578063d21220a714610715578063d505accf14610443578063dad0be61146103fd578063dd62ed3e14610382578063ddca3f431461033d5763fff6cae9146101a957600080fd5b3461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576101e56001600a5414612bd3565b80600a556024602073ffffffffffffffffffffffffffffffffffffffff60055416604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa801561032f5782906102fc575b60249150602073ffffffffffffffffffffffffffffffffffffffff60065416604051938480927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa9081156102f15783916102b6575b6102ae92506135fd565b6001600a5580f35b90506020823d6020116102e9575b816102d160209383612afb565b810103126102e4576102ae9151906102a4565b600080fd5b3d91506102c4565b6040513d85823e3d90fd5b506020813d602011610327575b8161031660209383612afb565b810103126102e45760249051610245565b3d9150610309565b6040513d84823e3d90fd5b80fd5b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602063ffffffff60095460401c16604051908152f35b503461033a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5773ffffffffffffffffffffffffffffffffffffffff60406103d1612ab5565b92826103db612ad8565b9416815260026020522091166000526020526020604060002054604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602067ffffffffffffffff60095416604051908152f35b503461033a5760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5761047b612ab5565b610483612ad8565b6044359060643560843560ff8116809103610711574282106106b35760035473ffffffffffffffffffffffffffffffffffffffff861692838852600460205260408820908154917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8314610686579282602095928b95600160809601905560405190878201927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9845289604084015273ffffffffffffffffffffffffffffffffffffffff8b1660608401528b8784015260a083015260c082015260c0815261056c60e082612afb565b51902060405190868201927f1901000000000000000000000000000000000000000000000000000000000000845260228301526042820152604281526105b3606282612afb565b519020906040519182528482015260a435604082015260c435606082015282805260015afa1561067b5773ffffffffffffffffffffffffffffffffffffffff855116908115159182610671575b50501561061357610610926138d2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f42726f776e466956323a20494e56414c49445f5349474e4154555245000000006044820152fd5b1490503880610600565b6040513d86823e3d90fd5b60248a7f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f42726f776e466956323a204558504952454400000000000000000000000000006044820152fd5b8580fd5b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602073ffffffffffffffffffffffffffffffffffffffff60065416604051908152f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760043567ffffffffffffffff8116809103610887576107ed73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314612d1e565b680100000000000000008111610829577fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000600954161760095580f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f42726f776e466956323a204d4158494d554d5f4c414d424441000000000000006044820152fd5b5080fd5b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57610932612ab5565b506102ae6001600a5414612bd3565b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760206040516103e88152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576020600854604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602060ff60055460a01c16604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602067ffffffffffffffff60095460601c16604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760206040516305f5e1008152f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760043563ffffffff8116810361088757610b0173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314612d1e565b7fffffffffffffffffffffffff0000000000000000ffffffffffffffffffffffff6fffffffff0000000000000000000000006009549260601b1691161760095580f35b503461033a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57610b89610b7f612ab5565b60243590336139a8565b602060405160018152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5750610c0b604051610bd5604082612afb565b600581527f42462d5632000000000000000000000000000000000000000000000000000000602082015260405191829182612b6b565b0390f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57610c47612ab5565b610c556001600a5414612bd3565b81600a556040517fb187bd2600000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa80156102f157610cd69184916110ab575b5015612c50565b73ffffffffffffffffffffffffffffffffffffffff600554169173ffffffffffffffffffffffffffffffffffffffff6006541691604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481885afa92831561109e57819361106a575b50604051937f70a08231000000000000000000000000000000000000000000000000000000008552306004860152602085602481845afa94851561032f578295611036575b503082526001602052610dc5610db9610db9610dbe60408620549786549384918a612ef4565b612d9c565b9787612ef4565b938515158061102d575b15610fa9576024968360209230825260018452610df0816040842054613935565b308352600185526040832055610e07818354613935565b82556040519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef843092a3610e3f878683612f2b565b610e4a868685612f2b565b604051978880927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa95861561032f578296610f74575b506020602491604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa918215610f685791610f35575b50610edc906040956135fd565b73ffffffffffffffffffffffffffffffffffffffff84519184835283602084015216907fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496853392a36001600a5582519182526020820152f35b90506020813d602011610f60575b81610f5060209383612afb565b810103126102e457516040610ecf565b3d9150610f43565b604051903d90823e3d90fd5b9095506020813d602011610fa1575b81610f9060209383612afb565b810103126102e45751946020610e8a565b3d9150610f83565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f42726f776e466956323a20494e53554646494349454e545f4c4951554944495460448201527f595f4255524e45440000000000000000000000000000000000000000000000006064820152fd5b50841515610dcf565b9094506020813d602011611062575b8161105260209383612afb565b810103126102e457519338610d93565b3d9150611045565b9092506020813d602011611096575b8161108660209383612afb565b810103126102e457519138610d4e565b3d9150611079565b50604051903d90823e3d90fd5b6110cd915060203d6020116110d3575b6110c58183612afb565b810190612c38565b38610ccf565b503d6110bb565b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57604060209173ffffffffffffffffffffffffffffffffffffffff61112c612ab5565b168152600483522054604051908152f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57604060209173ffffffffffffffffffffffffffffffffffffffff61118f612ab5565b168152600183522054604051908152f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576111d8612ab5565b906111e76001600a5414612bd3565b80600a556040517fb187bd2600000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561032f57906112699183916110ab575015612c50565b61129c6007546dffffffffffffffffffffffffffff8116916dffffffffffffffffffffffffffff8260701c169160e01c90565b5090600554604051947f70a0823100000000000000000000000000000000000000000000000000000000865230600487015260208660248173ffffffffffffffffffffffffffffffffffffffff86165afa95861561168c578596611658575b5060065491604051927f70a0823100000000000000000000000000000000000000000000000000000000845230600485015260208460248173ffffffffffffffffffffffffffffffffffffffff85165afa93841561164d578794611609575b506dffffffffffffffffffffffffffff60ff939495166dffffffffffffffffffffffffffff611389828b613935565b97166113958188613935565b9261139e6130cc565b96909560a01c169160ff6113b28b856137bd565b9260a01c16916113d6886113d0896113ca8a886137bd565b94612ef4565b92612ef4565b808210156116015750935b8b5493846115b25750505050506113f790612ea6565b60401c7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18810190811161158557966114326103e88254613a39565b8155808052600160205261144c6103e86040832054613a39565b81805260016020526040822055807fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60206040516103e88152a35b8615611501576114b873ffffffffffffffffffffffffffffffffffffffff956020996114b38a8861385e565b6135fd565b604051958652878601526040850152606084015216907f265ee4cff6cdf714e68c02e61a7864cf66bc04e372a41b6cc425acbb737cd39560803392a36001600a55604051908152f35b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f42726f776e466956323a20494e53554646494349454e545f4c4951554944495460448201527f595f4d494e5445440000000000000000000000000000000000000000000000006064820152fd5b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6115fb969c506115e16115db6115f5959697946115d56115ef956115e8956137bd565b976137bd565b93612ea6565b9488612ef4565b9188612ef4565b90613a39565b91613557565b95611487565b9050936113e1565b9293506020833d602011611645575b8161162560209383612afb565b810103126102e457915192916dffffffffffffffffffffffffffff61135a565b3d9150611618565b6040513d89823e3d90fd5b9095506020813d602011611684575b8161167460209383612afb565b810103126102e4575194386112fb565b3d9150611667565b6040513d87823e3d90fd5b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760043561170b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314612d1e565b6802000000000000000081116117215760085580f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f42726f776e466956323a204d4158494d554d5f4b0000000000000000000000006044820152fd5b503461033a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576117b7612ab5565b6117bf612ad8565b9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303611a6e5773ffffffffffffffffffffffffffffffffffffffff169081151580611a4f575b156119f15773ffffffffffffffffffffffffffffffffffffffff60055491837fffffffffffffffffffffffff0000000000000000000000000000000000000000841617600555169060065492827fffffffffffffffffffffffff00000000000000000000000000000000000000008516176006556040517f313ce567000000000000000000000000000000000000000000000000000000008152602081600481855afa9081156119e6577fffffffffffffffffffffff0000000000000000000000000000000000000000009174ff00000000000000000000000000000000000000009188916119c7575b5060a01b16921617176005556040517f313ce567000000000000000000000000000000000000000000000000000000008152602081600481855afa90811561067b577fffffffffffffffffffffff0000000000000000000000000000000000000000009174ff0000000000000000000000000000000000000000918691611998575b5060a01b169216171760065580f35b6119ba915060203d6020116119c0575b6119b28183612afb565b810190612d83565b38611989565b503d6119a8565b6119e0915060203d6020116119c0576119b28183612afb565b38611907565b6040513d88823e3d90fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f42726f776e466956323a205a45524f5f414444524553530000000000000000006044820152fd5b5073ffffffffffffffffffffffffffffffffffffffff8116151561181d565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f42726f776e466956323a20464f5242494444454e0000000000000000000000006044820152fd5b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576020600354604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576020604051680100000000000000008152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602060405160128152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760206040517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98152f35b503461033a5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57610b8990611c19612ab5565b611c21612ad8565b906044359273ffffffffffffffffffffffffffffffffffffffff82169081815260026020526040812073ffffffffffffffffffffffffffffffffffffffff33166000526020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60406000205403611c9b575b50506139a8565b808260409252600260205281812073ffffffffffffffffffffffffffffffffffffffff3316600052602052611cd4868360002054613935565b92815260026020522073ffffffffffffffffffffffffffffffffffffffff33166000526020526040600020553880611c94565b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760043563ffffffff8116810361088757611d8873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314612d1e565b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff6bffffffff00000000000000006009549260401b1691161760095580f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760209054604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602073ffffffffffffffffffffffffffffffffffffffff60055416604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602060ff60065460a01c16604051908152f35b503461033a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57610b89611ed1612ab5565b60243590336138d2565b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760606dffffffffffffffffffffffffffff63ffffffff611f536007546dffffffffffffffffffffffffffff8116916dffffffffffffffffffffffffffff8260701c169160e01c90565b9193908160405195168552166020840152166040820152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5750610c0b604051611fad604082612afb565b600a81527f42726f776e466920563200000000000000000000000000000000000000000000602082015260405191829182612b6b565b503461033a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576004359060243560443573ffffffffffffffffffffffffffffffffffffffff811691828203612ab1576064359067ffffffffffffffff8211612aad5736602383011215612aad5781600401359567ffffffffffffffff8711610711573660248885010111610711576120896001600a5414612bd3565b85600a5573ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166040517fb187bd26000000000000000000000000000000000000000000000000000000008152602081600481855afa908115612aa2579061210c9189916110ab575015612c50565b81159081158092612a99575b15612a15576121506007546dffffffffffffffffffffffffffff8116916dffffffffffffffffffffffffffff8260701c169160e01c90565b509690956dffffffffffffffffffffffffffff61216c86612dd5565b97169661217888612e83565b1015806129eb575b156129675773ffffffffffffffffffffffffffffffffffffffff600554169a73ffffffffffffffffffffffffffffffffffffffff60065416928c8b14158061295d575b156128ff578c8782886128ee575b50505087806128dd575b50508061281d575b5050602060249798999a604051988980927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa96871561249b578a976127e8575b506020602491604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa90811561249b578a916127b6575b5061227e8487612cb5565b8711156127a0576dffffffffffffffffffffffffffff6122a76122a18689612cb5565b89612cb5565b985b16966122b58689612cb5565b821115612799576122cf6122c9878a612cb5565b83612cb5565b935b89159182158093612790575b1561270d578c936122ec6130cc565b929093849b849d6009549167ffffffffffffffff83166126ee575b50508d918b61233c8f938f9061232f61233663ffffffff809360401c16958361232f88612cf1565b1690613397565b94612cf1565b9161264d575b508c61254e575b50505090612356916135fd565b6009549067ffffffffffffffff8260601c1691826123c3575b50505050505050604051958652602086015260408501526060840152608083015260a08201527f72362f8601a26e309bef1da8d6795550a593bd38f121bedcaf24be6e4b7c6bee60c03392a36001600a5580f35b8554938d6123d18483613727565b96612503575b5050876124a6575b5050505050806123f5575b808080808d9461236f565b6020600492604051938480927f017e7e580000000000000000000000000000000000000000000000000000000082525afa801561249b578a90612444575b61243d925061385e565b38806123ea565b50906020813d602011612493575b8161245f60209383612afb565b8101031261248f57519073ffffffffffffffffffffffffffffffffffffffff8216820361248f5761243d91612433565b8980fd5b3d9150612452565b6040513d8c823e3d90fd5b6124f995506124f492916124e86124ee9263ffffffff6124ce8c60ff60065460a01c166137bd565b9160401c1663ffffffff6124e182612cf1565b1691613557565b92612d0b565b90613448565b613557565b38808080806123df565b6125469297506124f487926124ee61253f6125278a9560ff60055460a01c166137bd565b63ffffffff8d60401c1663ffffffff6124e182612cf1565b9188612d0b565b94388d6123d7565b906125cf916125c96125c2879b6125bc88996115ef6125b561259861257e6125d59d60ff60055460a01c166137bd565b9861259260ff60065460a01c1695866137bd565b946137bd565b9760085495506125af6125aa85612ec9565b612ea6565b99612ef4565b918a612ef4565b96612ef4565b9180612ef4565b90613557565b90613935565b6125df8c8c613727565b116125ef57938d948b8b38612349565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f42726f776e466956323a20494e56414c49445f494e56454e544f5259000000006044820152fd5b91846125c96125c2886125bc6126c0986125cf979f986126956115ef9161268f61268060ff60055460a01c169a8b6137bd565b9660ff60065460a01c166137bd565b986137bd565b966113d0600854958c6000146126e757829c5b156126da576126ba6125aa869e612ec9565b9a612ef4565b6126ca8d8d613727565b116125ef578b8f968c9038612342565b6126ba6125aa8c9e612ec9565b809c6126a8565b8c9f508d929e50876127019288926132c8565b9e909d91508290612307565b60846040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f42726f776e466956323a20494e53554646494349454e545f494e5055545f414d60448201527f4f554e54000000000000000000000000000000000000000000000000000000006064820152fd5b508515156122dd565b8a936122d1565b6dffffffffffffffffffffffffffff8a986122a9565b90506020813d6020116127e0575b816127d160209383612afb565b810103126102e4575138612273565b3d91506127c4565b9096506020813d602011612815575b8161280460209383612afb565b810103126102e4575195602061222d565b3d91506127f7565b893b156128d9578660a4877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8f95806024604051998a9889977f6f9d78fc0000000000000000000000000000000000000000000000000000000089523360048a01528389015260448801526080606488015282608488015201868601378685828601015201168101030181838d5af1801561249b576128bf575b806121e3565b896128d06024999a9b602093612afb565b999897506128b9565b8a80fd5b6128e79185612f2b565b38876121db565b6128f792612f2b565b8c87826121d1565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f42726f776e466956323a20494e56414c49445f544f00000000000000000000006044820152fd5b50838b14156121c3565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f42726f776e466956323a20494e53554646494349454e545f4c4951554944495460448201527f59000000000000000000000000000000000000000000000000000000000000006064820152fd5b506129f586612dd5565b612a0e6dffffffffffffffffffffffffffff8a16612e83565b1015612180565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f42726f776e466956323a20494e53554646494349454e545f4f55545055545f4160448201527f4d4f554e540000000000000000000000000000000000000000000000000000006064820152fd5b50831515612118565b6040513d8a823e3d90fd5b8480fd5b8380fd5b6004359073ffffffffffffffffffffffffffffffffffffffff821682036102e457565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036102e457565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612b3c57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b9190916020815282519283602083015260005b848110612bbd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b8060208092840101516040828601015201612b7e565b15612bda57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f42726f776e466956323a204c4f434b45440000000000000000000000000000006044820152fd5b908160209103126102e4575180151581036102e45790565b15612c5757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f42726f776e466956323a205041555345440000000000000000000000000000006044820152fd5b91908203918211612cc257565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff166305f5e100019063ffffffff8211612cc257565b81810292918115918404141715612cc257565b15612d2557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f42726f776e466956323a204f4e4c595f464143544f52590000000000000000006044820152fd5b908160209103126102e4575160ff811681036102e45790565b8115612da6570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b90600091600a8102818104600a1482151715612e56579250600a830403612df857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f770000000000000000000000006044820152fd5b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b906000916008810281810460081482151715612e565780935060031c03612df857565b906000916002810281810460021482151715612e565780935060011c03612df857565b9060009168010000000000000000808202908282041482151715612e565780935060401c03612df857565b600092918015918215612f0b575b505015612df857565b91509250612f23612f1c8483612d0b565b9384612d9c565b143880612f02565b60009190829182604095612fd07fffffffff00000000000000000000000000000000000000000000000000000000601960208a51612f698c82612afb565b8281527f7472616e7366657228616464726573732c75696e743235362900000000000000910190815220895191166020820190815273ffffffffffffffffffffffffffffffffffffffff959095166024820152604480820193909352918252606482612afb565b51925af13d156130c5573d67ffffffffffffffff8111612b3c5782519061301f601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200183612afb565b81523d6000602083013e5b81613096575b50156130395750565b606490517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f42726f776e466956323a205452414e534645525f4641494c45440000000000006044820152fd5b80518015925082156130ab575b505038613030565b6130be9250602080918301019101612c38565b38806130a3565b606061302a565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906040517f67cc3403000000000000000000000000000000000000000000000000000000008152602081600481865afa90811561324957600091613289575b506005546040517ffc3d545d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101829052602081604481875afa90811561324957600091613255575b506006546040517ffc3d545d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101929092529260209082908180604481015b03915afa9081156132495760009161321a575090565b90506020813d602011613241575b8161323560209383612afb565b810103126102e4575190565b3d9150613228565b6040513d6000823e3d90fd5b90506020813d602011613281575b8161327060209383612afb565b810103126102e457516132046131a8565b3d9150613263565b906020823d6020116132b3575b816132a360209383612afb565b8101031261033a57505138613142565b3d9150613296565b91908201809211612cc257565b6132f7846132f1856132eb61268061332a969a999a60ff60055460a01c166137bd565b95612d0b565b93612d0b565b808310801593916133169161338d576133108184612cb5565b926132bb565b9067ffffffffffffffff6009541690613557565b9182680100000000000000000192836801000000000000000011612cc257680100000000000000000391680100000000000000008311612cc257156133805761337d9291613377916134e0565b936134e0565b90565b61337d92613377916134e0565b6133108382612cb5565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6305f5e1008209916305f5e10082029182808510940393808503941461343b57838211156102e4576305f5e100829109818060000316809204600281600302188082026002030280820260020302808202600203028082026002030280820260020302809102600203029360018380600003040190848311900302920304170290565b50809250156102e4570490565b9190916000907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84820990848102928380841093039280840393146134d157826305f5e100111561033a57507facbe0e98f503f8881186e60dbb7f727bf36b7213ee9f5a78c767074b22e90e2193946305f5e100910990828211900360f81b910360081c170290565b5050506305f5e1009192500490565b6000917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818309918181029384808510940393808503941461354d578368010000000000000000111561033a57509068010000000000000000910990828211900360c01b910360401c1790565b5050505060401c90565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82840992828102928380861095039480860395146135ef57848311156102e457829109818060000316809204600281600302188082026002030280820260020302808202600203028082026002030280820260020302809102600203029360018380600003040190848311900302920304170290565b5050809250156102e4570490565b6dffffffffffffffffffffffffffff8111158061370f575b156136b1577f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1916dffffffffffffffffffffffffffff806040931691827bffffffffffffffffffffffffffff00000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000004260e01b169260701b16171780600755835192835260701c166020820152a1565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f42726f776e466956323a204f564552464c4f57000000000000000000000000006044820152fd5b506dffffffffffffffffffffffffffff821115613615565b906115ef61337d926113d061378e6113d061376b6007546dffffffffffffffffffffffffffff8116916dffffffffffffffffffffffffffff8260701c169160e01c90565b5092906dffffffffffffffffffffffffffff60ff60055460a01c169116906137bd565b916dffffffffffffffffffffffffffff60ff60065460a01c169116906137bd565b604d8111612cc257600a0a90565b60009060ff16601281111561380e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee9150019060ff8211612cc25761380860ff61337d93166137af565b90612d9c565b6012039060ff821161383157509061382b60ff61337d93166137af565b90612d0b565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602073ffffffffffffffffffffffffffffffffffffffff6000936138a4868654613a39565b85551693848452600182526138bd816040862054613a39565b858552600183526040852055604051908152a3565b602073ffffffffffffffffffffffffffffffffffffffff807f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925931693846000526002835260406000208282166000528352856040600020556040519586521693a3565b91906139419083612cb5565b91821161394a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f7700000000000000000000006044820152fd5b602073ffffffffffffffffffffffffffffffffffffffff807fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93169384600052600183526139fb86604060002054613935565b856000526001845260406000205516938460005260018252613a2281604060002054613a39565b8560005260018352604060002055604051908152a3565b9190613a4590836132bb565b918210613a4e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f770000000000000000000000006044820152fdfea26469706673582212201634120ea8a3571b194d610828716ad7c6c5e7329387eff50ccf0bdb13b8557b64736f6c634300081c0033a264697066735822122035f522e0dab5d23d6b4b333f20f840c30daaef0d2b6228a20897e541397bab0164736f6c634300081c00330000000000000000000000003f0bbeedea5e5f63a14cbda82718d4f25501fbea00000000000000000000000068bc42f886ddf6a4b0b90a9496493da1f8304536
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c8063017e7e581461019257806316c38b3c1461018d5780631e3dd18b146101885780632630c12f14610183578063336eb6ae1461017e57806333fca1871461017957806334667c1414610174578063530e784f1461016f578063574f2ba31461016a5780635c975abb1461014257806367cc34031461016557806378b2cd7d146101605780637a9e5e4b1461015b5780637e058f501461015657806388df8516146101515780638fb360371461014c578063b03b9f1f14610147578063b187bd2614610142578063bf7e214f1461013d578063cb3d74aa14610138578063e6a4390514610133578063e6bc07931461012e578063f46901ed146101295763fc3d545d1461012457600080fd5b611577565b6114f2565b611348565b6112b1565b6110e9565b611097565b6105a2565b610f4b565b610eb7565b610a67565b6109d5565b610897565b6106a1565b6105e6565b610566565b6104e1565b610475565b610433565b6103ce565b610336565b6102b1565b6101f9565b6101a7565b60009103126101a257565b600080fd5b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576004358015158091036101a25760207f4543baa938cb97f5073ec206ad35638cdb1f4db8f677d31579b2f6fe7d18c14a916102633633611bb4565b6002547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000008360a01b16911617600255604051908152a1005b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576004356006548110156101a25773ffffffffffffffffffffffffffffffffffffffff60209160066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f015416604051908152f35b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101a257565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036101a257565b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25773ffffffffffffffffffffffffffffffffffffffff61041a610388565b1660005260046020526020604060002054604051908152f35b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576020604051680100000000000000008152f35b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2577f4cce7b74bd7749107683fee0f1ad5547d2dcf7c7d893d93e20bdeadb1909395e60206004356104d43633611bb4565b80600355604051908152a1005b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25773ffffffffffffffffffffffffffffffffffffffff61052d610388565b6105373633611bb4565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006001541617600155600080f35b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576020600654604051908152f35b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602060ff60025460a01c166040519015158152f35b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576020600354604051908152f35b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60609101126101a25760043573ffffffffffffffffffffffffffffffffffffffff811681036101a2579060243573ffffffffffffffffffffffffffffffffffffffff811681036101a2579060443563ffffffff811681036101a25790565b346101a2576106af36610622565b91906107cf6107b66107b661079c8461077773ffffffffffffffffffffffffffffffffffffffff88169788600052600560205261073173ffffffffffffffffffffffffffffffffffffffff6107288560406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54161515611678565b61073b3633611bb4565b6107516304c4b40063ffffffff8c1611156116dd565b73ffffffffffffffffffffffffffffffffffffffff166000526005602052604060002090565b9073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b90813b156101a2576040517faa9f762800000000000000000000000000000000000000000000000000000000815263ffffffff85166004820152916000908390602490829084905af1908115610892577fe05b718c2e5d9ba7d193e3f618d623817996e0f922635158d409e31d00ee42c99273ffffffffffffffffffffffffffffffffffffffff92610877575b5060405163ffffffff9095168552169280602081015b0390a3005b80610886600061088c93611771565b80610197565b3861085c565b6117b7565b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576108ce610388565b6000549073ffffffffffffffffffffffffffffffffffffffff821633036109a757803b15610963577fffffffffffffffffffffffff00000000000000000000000000000000000000007f2f658b440c35314f52658ea8a740e05b284cdc84dc9ae01e891f21b8933e7cad9273ffffffffffffffffffffffffffffffffffffffff602093169182911617600055604051908152a1005b73ffffffffffffffffffffffffffffffffffffffff907fc2f31e5e000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b7f068ca9d8000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b346101a25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257610a0c610388565b7f35384503a4bc4d7d46a62b5e5973108c35f47b598b11199d085e8ce2b8043cdd602073ffffffffffffffffffffffffffffffffffffffff60243593610a523633611bb4565b610a5c8582611d4e565b6040519485521692a2005b346101a25760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257610a9e610388565b610aa66103ab565b9060443560643590610ae2610ade8473ffffffffffffffffffffffffffffffffffffffff166000526004602052604060002054151590565b1590565b610ea7575b50610b18610ade8473ffffffffffffffffffffffffffffffffffffffff166000526004602052604060002054151590565b610e97575b50610b53610b4e8273ffffffffffffffffffffffffffffffffffffffff166000526004602052604060002054151590565b6117c3565b610b88610b838373ffffffffffffffffffffffffffffffffffffffff166000526004602052604060002054151590565b611828565b73ffffffffffffffffffffffffffffffffffffffff821673ffffffffffffffffffffffffffffffffffffffff8216610bc28282141561188d565b1015610e9257905b73ffffffffffffffffffffffffffffffffffffffff821690610bed8215156118f2565b610c2a610c246107b661079c846107778873ffffffffffffffffffffffffffffffffffffffff166000526005602052604060002090565b15611957565b613c76610c39602082016119bc565b908082526020820190611e4282396040516020810190610cbf81610c93878a86906028927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000809260601b16835260601b1660148201520190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611771565b5190209151906000f59173ffffffffffffffffffffffffffffffffffffffff831693843b156101a2576040517f485cc95500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff828116600483015284166024820152946000908690604490829084905af194851561089257610d8d610df7928692610e7998610e7d575b50610dcd83610d8d886107778573ffffffffffffffffffffffffffffffffffffffff166000526005602052604060002090565b9073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b6107778673ffffffffffffffffffffffffffffffffffffffff166000526005602052604060002090565b610e00836119cc565b6006546040805173ffffffffffffffffffffffffffffffffffffffff8681168252602082019390935293909116927f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e99190a360405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b806108866000610e8c93611771565b38610d5a565b610bca565b610ea19083611d4e565b38610b1d565b610eb19083611d4e565b38610ae7565b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25760005460a01c60ff1615610f425760207f8fb36037000000000000000000000000000000000000000000000000000000005b7fffffffff0000000000000000000000000000000000000000000000000000000060405191168152f35b60206000610f18565b346101a257610f5936610622565b9190610ff16107b66107b661079c8461077773ffffffffffffffffffffffffffffffffffffffff881697886000526005602052610fd273ffffffffffffffffffffffffffffffffffffffff6107288560406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b610fdc3633611bb4565b6107516298968063ffffffff8c161115611a6a565b90813b156101a2576040517f1ab971ab00000000000000000000000000000000000000000000000000000000815263ffffffff85166004820152916000908390602490829084905af1908115610892577f6e1c36e9b395976f59344b51646e14ddbbdbdea13050432e2d6dfce4ebaced6c9273ffffffffffffffffffffffffffffffffffffffff92610877575060405163ffffffff909516855216928060208101610872565b346101a25760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b346101a25760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257611120610388565b6111286103ab565b6044359167ffffffffffffffff831683036101a25773ffffffffffffffffffffffffffffffffffffffff16908160005260056020526111a373ffffffffffffffffffffffffffffffffffffffff6107288360406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b6111ad3633611bb4565b8160005260056020526111ed6107b66107b661079c8460406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b90813b156101a2576040517fcde5bf5300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152916000908390602490829084905af1908115610892577f675db29b8feddf09b6825fa7ae35928c772c56488772a384b474236449b4399e9273ffffffffffffffffffffffffffffffffffffffff9261129c575b5060405167ffffffffffffffff909516855216928060208101610872565b8061088660006112ab93611771565b3861127e565b346101a25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602073ffffffffffffffffffffffffffffffffffffffff61133e611302610388565b8261130b6103ab565b91166000526005845260406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5416604051908152f35b346101a25760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25761137f610388565b6113876103ab565b73ffffffffffffffffffffffffffffffffffffffff6044359216908160005260056020526113f173ffffffffffffffffffffffffffffffffffffffff6107288360406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b6113fb3633611bb4565b81600052600560205261143b6107b66107b661079c8460406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b90813b156101a257600060405180937f67de8be90000000000000000000000000000000000000000000000000000000082528183816114828a600483019190602083019252565b03925af1908115610892577f5424eaf93192b9cbb2ace7d1be43b65df9933b2f307857b698a3eb7f22a2fabb9273ffffffffffffffffffffffffffffffffffffffff926114dd575b5060405194855216928060208101610872565b8061088660006114ec93611771565b386114ca565b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25773ffffffffffffffffffffffffffffffffffffffff61153e610388565b6115483633611bb4565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255600080f35b346101a25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25761162260206115b3610388565b6024359073ffffffffffffffffffffffffffffffffffffffff80600154169116600052600483526040600020546040518095819482937fc9280f060000000000000000000000000000000000000000000000000000000084526004840160209093929193604081019481520152565b03915afa801561089257610e7991600091611649575b506040519081529081906020820190565b61166b915060203d602011611671575b6116638183611771565b810190611acf565b38611638565b503d611659565b1561167f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f42726f776e466956323a20504149525f4e4f545f4558495354530000000000006044820152fd5b156116e457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f42726f776e466956323a2050524f544f434f4c5f4645455f544f4f5f484947486044820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176117b257604052565b611742565b6040513d6000823e3d90fd5b156117ca57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f42726f776e466956323a204f5241434c455f415f5245515549524544000000006044820152fd5b1561182f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f42726f776e466956323a204f5241434c455f425f5245515549524544000000006044820152fd5b1561189457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f42726f776e466956323a204944454e544943414c5f41444452455353455300006044820152fd5b156118f957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f42726f776e466956323a205a45524f5f414444524553530000000000000000006044820152fd5b1561195e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f42726f776e466956323a20504149525f455849535453000000000000000000006044820152fd5b906119ca6040519283611771565b565b600654680100000000000000008110156117b257600181016006556000600654821015611a3d5790602082600673ffffffffffffffffffffffffffffffffffffffff9452200191167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526032600452fd5b15611a7157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f42726f776e466956323a204645455f544f4f5f484947480000000000000000006044820152fd5b908160209103126101a2575190565b906004116101a25790600490565b919091357fffffffff0000000000000000000000000000000000000000000000000000000081169260048110611b20575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b9183606094601f9273ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe095168652604060208701528160408701528686013760008582860101520116010190565b611bf3611bd660005473ffffffffffffffffffffffffffffffffffffffff1690565b611bea611be4856000611ade565b90611aec565b90833091611d8d565b9015611bfe57505050565b63ffffffff1615611d0b57611c4d740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff6000541617600055565b611c726107b66107b660005473ffffffffffffffffffffffffffffffffffffffff1690565b91823b156101a257611cb9926000808094604051968795869485937f94c7d7ee00000000000000000000000000000000000000000000000000000000855260048501611b52565b03925af1801561089257611cf6575b506119ca7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff60005416600055565b806108866000611d0593611771565b38611cc8565b7f068ca9d80000000000000000000000000000000000000000000000000000000060005273ffffffffffffffffffffffffffffffffffffffff1660045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff1680158015611d85575b611d81576000526004602052604060002055565b5050565b508115611d6d565b60009060409295939582967fffffffff00000000000000000000000000000000000000000000000000000000849773ffffffffffffffffffffffffffffffffffffffff8751938160208601967fb700961300000000000000000000000000000000000000000000000000000000885216602486015216604484015216606482015260648152611e1d608482611771565b8380528360205251915afa611e2e57565b915050600051906020518060201c15029056fe60a0604052346101555760405161001760408261015a565b600a815269213937bbb72334902b1960b11b602090910152604080517f6734371cf3152a7df61c4623a003b33fdd6df5cdf7648e19ad4b1d9eababb5159161005f908261015a565b600181526020810190603160f81b82525190206040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a081526100c360c08261015a565b519020600355664189374bc6a7ef600855600980546001600160a01b0319166e989680000493e000000000000000001790556001600a5533608052604051613ae2908161019482396080518181816107c6015281816108d601528181610ada01528181610c9c0152818161122e015281816116e4015281816117d701528181611d61015281816120a401526130e30152f35b600080fd5b601f909101601f19168101906001600160401b0382119082101761017d57604052565b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c8063022c0d9f14611fe357806306fdde0314611f6c5780630902f1ac14611edb578063095ea7b314611e965780630b77884d14611e545780630dfe168114611e0257806318160ddd14611dc75780631ab971ab14611d0757806323b872dd14611bdd57806330adf81f14611b84578063313ce56714611b4a57806333fca18714611b085780633644e51514611acc578063485cc9551461177f57806367de8be9146116975780636a627842146111a057806370a082311461113d5780637ecebe00146110da57806389afcb4414610c0f57806395d89b4114610b94578063a9059cbb14610b44578063aa9f762814610a80578063aaf5eb6814610a43578063b0e21e8a146109fa578063b31ac6e2146109b8578063b4f40c611461097c578063ba9a7a5614610941578063bc25cf77146108fa578063c45a01551461088b578063cde5bf5314610767578063d21220a714610715578063d505accf14610443578063dad0be61146103fd578063dd62ed3e14610382578063ddca3f431461033d5763fff6cae9146101a957600080fd5b3461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576101e56001600a5414612bd3565b80600a556024602073ffffffffffffffffffffffffffffffffffffffff60055416604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa801561032f5782906102fc575b60249150602073ffffffffffffffffffffffffffffffffffffffff60065416604051938480927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa9081156102f15783916102b6575b6102ae92506135fd565b6001600a5580f35b90506020823d6020116102e9575b816102d160209383612afb565b810103126102e4576102ae9151906102a4565b600080fd5b3d91506102c4565b6040513d85823e3d90fd5b506020813d602011610327575b8161031660209383612afb565b810103126102e45760249051610245565b3d9150610309565b6040513d84823e3d90fd5b80fd5b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602063ffffffff60095460401c16604051908152f35b503461033a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5773ffffffffffffffffffffffffffffffffffffffff60406103d1612ab5565b92826103db612ad8565b9416815260026020522091166000526020526020604060002054604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602067ffffffffffffffff60095416604051908152f35b503461033a5760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5761047b612ab5565b610483612ad8565b6044359060643560843560ff8116809103610711574282106106b35760035473ffffffffffffffffffffffffffffffffffffffff861692838852600460205260408820908154917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8314610686579282602095928b95600160809601905560405190878201927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9845289604084015273ffffffffffffffffffffffffffffffffffffffff8b1660608401528b8784015260a083015260c082015260c0815261056c60e082612afb565b51902060405190868201927f1901000000000000000000000000000000000000000000000000000000000000845260228301526042820152604281526105b3606282612afb565b519020906040519182528482015260a435604082015260c435606082015282805260015afa1561067b5773ffffffffffffffffffffffffffffffffffffffff855116908115159182610671575b50501561061357610610926138d2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f42726f776e466956323a20494e56414c49445f5349474e4154555245000000006044820152fd5b1490503880610600565b6040513d86823e3d90fd5b60248a7f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f42726f776e466956323a204558504952454400000000000000000000000000006044820152fd5b8580fd5b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602073ffffffffffffffffffffffffffffffffffffffff60065416604051908152f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760043567ffffffffffffffff8116809103610887576107ed73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314612d1e565b680100000000000000008111610829577fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000600954161760095580f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f42726f776e466956323a204d4158494d554d5f4c414d424441000000000000006044820152fd5b5080fd5b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57610932612ab5565b506102ae6001600a5414612bd3565b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760206040516103e88152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576020600854604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602060ff60055460a01c16604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602067ffffffffffffffff60095460601c16604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760206040516305f5e1008152f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760043563ffffffff8116810361088757610b0173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314612d1e565b7fffffffffffffffffffffffff0000000000000000ffffffffffffffffffffffff6fffffffff0000000000000000000000006009549260601b1691161760095580f35b503461033a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57610b89610b7f612ab5565b60243590336139a8565b602060405160018152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5750610c0b604051610bd5604082612afb565b600581527f42462d5632000000000000000000000000000000000000000000000000000000602082015260405191829182612b6b565b0390f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57610c47612ab5565b610c556001600a5414612bd3565b81600a556040517fb187bd2600000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa80156102f157610cd69184916110ab575b5015612c50565b73ffffffffffffffffffffffffffffffffffffffff600554169173ffffffffffffffffffffffffffffffffffffffff6006541691604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481885afa92831561109e57819361106a575b50604051937f70a08231000000000000000000000000000000000000000000000000000000008552306004860152602085602481845afa94851561032f578295611036575b503082526001602052610dc5610db9610db9610dbe60408620549786549384918a612ef4565b612d9c565b9787612ef4565b938515158061102d575b15610fa9576024968360209230825260018452610df0816040842054613935565b308352600185526040832055610e07818354613935565b82556040519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef843092a3610e3f878683612f2b565b610e4a868685612f2b565b604051978880927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa95861561032f578296610f74575b506020602491604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa918215610f685791610f35575b50610edc906040956135fd565b73ffffffffffffffffffffffffffffffffffffffff84519184835283602084015216907fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496853392a36001600a5582519182526020820152f35b90506020813d602011610f60575b81610f5060209383612afb565b810103126102e457516040610ecf565b3d9150610f43565b604051903d90823e3d90fd5b9095506020813d602011610fa1575b81610f9060209383612afb565b810103126102e45751946020610e8a565b3d9150610f83565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f42726f776e466956323a20494e53554646494349454e545f4c4951554944495460448201527f595f4255524e45440000000000000000000000000000000000000000000000006064820152fd5b50841515610dcf565b9094506020813d602011611062575b8161105260209383612afb565b810103126102e457519338610d93565b3d9150611045565b9092506020813d602011611096575b8161108660209383612afb565b810103126102e457519138610d4e565b3d9150611079565b50604051903d90823e3d90fd5b6110cd915060203d6020116110d3575b6110c58183612afb565b810190612c38565b38610ccf565b503d6110bb565b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57604060209173ffffffffffffffffffffffffffffffffffffffff61112c612ab5565b168152600483522054604051908152f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57604060209173ffffffffffffffffffffffffffffffffffffffff61118f612ab5565b168152600183522054604051908152f35b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576111d8612ab5565b906111e76001600a5414612bd3565b80600a556040517fb187bd2600000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561032f57906112699183916110ab575015612c50565b61129c6007546dffffffffffffffffffffffffffff8116916dffffffffffffffffffffffffffff8260701c169160e01c90565b5090600554604051947f70a0823100000000000000000000000000000000000000000000000000000000865230600487015260208660248173ffffffffffffffffffffffffffffffffffffffff86165afa95861561168c578596611658575b5060065491604051927f70a0823100000000000000000000000000000000000000000000000000000000845230600485015260208460248173ffffffffffffffffffffffffffffffffffffffff85165afa93841561164d578794611609575b506dffffffffffffffffffffffffffff60ff939495166dffffffffffffffffffffffffffff611389828b613935565b97166113958188613935565b9261139e6130cc565b96909560a01c169160ff6113b28b856137bd565b9260a01c16916113d6886113d0896113ca8a886137bd565b94612ef4565b92612ef4565b808210156116015750935b8b5493846115b25750505050506113f790612ea6565b60401c7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18810190811161158557966114326103e88254613a39565b8155808052600160205261144c6103e86040832054613a39565b81805260016020526040822055807fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60206040516103e88152a35b8615611501576114b873ffffffffffffffffffffffffffffffffffffffff956020996114b38a8861385e565b6135fd565b604051958652878601526040850152606084015216907f265ee4cff6cdf714e68c02e61a7864cf66bc04e372a41b6cc425acbb737cd39560803392a36001600a55604051908152f35b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f42726f776e466956323a20494e53554646494349454e545f4c4951554944495460448201527f595f4d494e5445440000000000000000000000000000000000000000000000006064820152fd5b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6115fb969c506115e16115db6115f5959697946115d56115ef956115e8956137bd565b976137bd565b93612ea6565b9488612ef4565b9188612ef4565b90613a39565b91613557565b95611487565b9050936113e1565b9293506020833d602011611645575b8161162560209383612afb565b810103126102e457915192916dffffffffffffffffffffffffffff61135a565b3d9150611618565b6040513d89823e3d90fd5b9095506020813d602011611684575b8161167460209383612afb565b810103126102e4575194386112fb565b3d9150611667565b6040513d87823e3d90fd5b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760043561170b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314612d1e565b6802000000000000000081116117215760085580f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f42726f776e466956323a204d4158494d554d5f4b0000000000000000000000006044820152fd5b503461033a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576117b7612ab5565b6117bf612ad8565b9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303611a6e5773ffffffffffffffffffffffffffffffffffffffff169081151580611a4f575b156119f15773ffffffffffffffffffffffffffffffffffffffff60055491837fffffffffffffffffffffffff0000000000000000000000000000000000000000841617600555169060065492827fffffffffffffffffffffffff00000000000000000000000000000000000000008516176006556040517f313ce567000000000000000000000000000000000000000000000000000000008152602081600481855afa9081156119e6577fffffffffffffffffffffff0000000000000000000000000000000000000000009174ff00000000000000000000000000000000000000009188916119c7575b5060a01b16921617176005556040517f313ce567000000000000000000000000000000000000000000000000000000008152602081600481855afa90811561067b577fffffffffffffffffffffff0000000000000000000000000000000000000000009174ff0000000000000000000000000000000000000000918691611998575b5060a01b169216171760065580f35b6119ba915060203d6020116119c0575b6119b28183612afb565b810190612d83565b38611989565b503d6119a8565b6119e0915060203d6020116119c0576119b28183612afb565b38611907565b6040513d88823e3d90fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f42726f776e466956323a205a45524f5f414444524553530000000000000000006044820152fd5b5073ffffffffffffffffffffffffffffffffffffffff8116151561181d565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f42726f776e466956323a20464f5242494444454e0000000000000000000000006044820152fd5b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576020600354604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576020604051680100000000000000008152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602060405160128152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760206040517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98152f35b503461033a5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57610b8990611c19612ab5565b611c21612ad8565b906044359273ffffffffffffffffffffffffffffffffffffffff82169081815260026020526040812073ffffffffffffffffffffffffffffffffffffffff33166000526020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60406000205403611c9b575b50506139a8565b808260409252600260205281812073ffffffffffffffffffffffffffffffffffffffff3316600052602052611cd4868360002054613935565b92815260026020522073ffffffffffffffffffffffffffffffffffffffff33166000526020526040600020553880611c94565b503461033a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760043563ffffffff8116810361088757611d8873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163314612d1e565b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff6bffffffff00000000000000006009549260401b1691161760095580f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760209054604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602073ffffffffffffffffffffffffffffffffffffffff60055416604051908152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57602060ff60065460a01c16604051908152f35b503461033a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a57610b89611ed1612ab5565b60243590336138d2565b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5760606dffffffffffffffffffffffffffff63ffffffff611f536007546dffffffffffffffffffffffffffff8116916dffffffffffffffffffffffffffff8260701c169160e01c90565b9193908160405195168552166020840152166040820152f35b503461033a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a5750610c0b604051611fad604082612afb565b600a81527f42726f776e466920563200000000000000000000000000000000000000000000602082015260405191829182612b6b565b503461033a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033a576004359060243560443573ffffffffffffffffffffffffffffffffffffffff811691828203612ab1576064359067ffffffffffffffff8211612aad5736602383011215612aad5781600401359567ffffffffffffffff8711610711573660248885010111610711576120896001600a5414612bd3565b85600a5573ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166040517fb187bd26000000000000000000000000000000000000000000000000000000008152602081600481855afa908115612aa2579061210c9189916110ab575015612c50565b81159081158092612a99575b15612a15576121506007546dffffffffffffffffffffffffffff8116916dffffffffffffffffffffffffffff8260701c169160e01c90565b509690956dffffffffffffffffffffffffffff61216c86612dd5565b97169661217888612e83565b1015806129eb575b156129675773ffffffffffffffffffffffffffffffffffffffff600554169a73ffffffffffffffffffffffffffffffffffffffff60065416928c8b14158061295d575b156128ff578c8782886128ee575b50505087806128dd575b50508061281d575b5050602060249798999a604051988980927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa96871561249b578a976127e8575b506020602491604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa90811561249b578a916127b6575b5061227e8487612cb5565b8711156127a0576dffffffffffffffffffffffffffff6122a76122a18689612cb5565b89612cb5565b985b16966122b58689612cb5565b821115612799576122cf6122c9878a612cb5565b83612cb5565b935b89159182158093612790575b1561270d578c936122ec6130cc565b929093849b849d6009549167ffffffffffffffff83166126ee575b50508d918b61233c8f938f9061232f61233663ffffffff809360401c16958361232f88612cf1565b1690613397565b94612cf1565b9161264d575b508c61254e575b50505090612356916135fd565b6009549067ffffffffffffffff8260601c1691826123c3575b50505050505050604051958652602086015260408501526060840152608083015260a08201527f72362f8601a26e309bef1da8d6795550a593bd38f121bedcaf24be6e4b7c6bee60c03392a36001600a5580f35b8554938d6123d18483613727565b96612503575b5050876124a6575b5050505050806123f5575b808080808d9461236f565b6020600492604051938480927f017e7e580000000000000000000000000000000000000000000000000000000082525afa801561249b578a90612444575b61243d925061385e565b38806123ea565b50906020813d602011612493575b8161245f60209383612afb565b8101031261248f57519073ffffffffffffffffffffffffffffffffffffffff8216820361248f5761243d91612433565b8980fd5b3d9150612452565b6040513d8c823e3d90fd5b6124f995506124f492916124e86124ee9263ffffffff6124ce8c60ff60065460a01c166137bd565b9160401c1663ffffffff6124e182612cf1565b1691613557565b92612d0b565b90613448565b613557565b38808080806123df565b6125469297506124f487926124ee61253f6125278a9560ff60055460a01c166137bd565b63ffffffff8d60401c1663ffffffff6124e182612cf1565b9188612d0b565b94388d6123d7565b906125cf916125c96125c2879b6125bc88996115ef6125b561259861257e6125d59d60ff60055460a01c166137bd565b9861259260ff60065460a01c1695866137bd565b946137bd565b9760085495506125af6125aa85612ec9565b612ea6565b99612ef4565b918a612ef4565b96612ef4565b9180612ef4565b90613557565b90613935565b6125df8c8c613727565b116125ef57938d948b8b38612349565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f42726f776e466956323a20494e56414c49445f494e56454e544f5259000000006044820152fd5b91846125c96125c2886125bc6126c0986125cf979f986126956115ef9161268f61268060ff60055460a01c169a8b6137bd565b9660ff60065460a01c166137bd565b986137bd565b966113d0600854958c6000146126e757829c5b156126da576126ba6125aa869e612ec9565b9a612ef4565b6126ca8d8d613727565b116125ef578b8f968c9038612342565b6126ba6125aa8c9e612ec9565b809c6126a8565b8c9f508d929e50876127019288926132c8565b9e909d91508290612307565b60846040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f42726f776e466956323a20494e53554646494349454e545f494e5055545f414d60448201527f4f554e54000000000000000000000000000000000000000000000000000000006064820152fd5b508515156122dd565b8a936122d1565b6dffffffffffffffffffffffffffff8a986122a9565b90506020813d6020116127e0575b816127d160209383612afb565b810103126102e4575138612273565b3d91506127c4565b9096506020813d602011612815575b8161280460209383612afb565b810103126102e4575195602061222d565b3d91506127f7565b893b156128d9578660a4877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8f95806024604051998a9889977f6f9d78fc0000000000000000000000000000000000000000000000000000000089523360048a01528389015260448801526080606488015282608488015201868601378685828601015201168101030181838d5af1801561249b576128bf575b806121e3565b896128d06024999a9b602093612afb565b999897506128b9565b8a80fd5b6128e79185612f2b565b38876121db565b6128f792612f2b565b8c87826121d1565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f42726f776e466956323a20494e56414c49445f544f00000000000000000000006044820152fd5b50838b14156121c3565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f42726f776e466956323a20494e53554646494349454e545f4c4951554944495460448201527f59000000000000000000000000000000000000000000000000000000000000006064820152fd5b506129f586612dd5565b612a0e6dffffffffffffffffffffffffffff8a16612e83565b1015612180565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f42726f776e466956323a20494e53554646494349454e545f4f55545055545f4160448201527f4d4f554e540000000000000000000000000000000000000000000000000000006064820152fd5b50831515612118565b6040513d8a823e3d90fd5b8480fd5b8380fd5b6004359073ffffffffffffffffffffffffffffffffffffffff821682036102e457565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036102e457565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612b3c57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b9190916020815282519283602083015260005b848110612bbd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b8060208092840101516040828601015201612b7e565b15612bda57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f42726f776e466956323a204c4f434b45440000000000000000000000000000006044820152fd5b908160209103126102e4575180151581036102e45790565b15612c5757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f42726f776e466956323a205041555345440000000000000000000000000000006044820152fd5b91908203918211612cc257565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff166305f5e100019063ffffffff8211612cc257565b81810292918115918404141715612cc257565b15612d2557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f42726f776e466956323a204f4e4c595f464143544f52590000000000000000006044820152fd5b908160209103126102e4575160ff811681036102e45790565b8115612da6570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b90600091600a8102818104600a1482151715612e56579250600a830403612df857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f770000000000000000000000006044820152fd5b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b906000916008810281810460081482151715612e565780935060031c03612df857565b906000916002810281810460021482151715612e565780935060011c03612df857565b9060009168010000000000000000808202908282041482151715612e565780935060401c03612df857565b600092918015918215612f0b575b505015612df857565b91509250612f23612f1c8483612d0b565b9384612d9c565b143880612f02565b60009190829182604095612fd07fffffffff00000000000000000000000000000000000000000000000000000000601960208a51612f698c82612afb565b8281527f7472616e7366657228616464726573732c75696e743235362900000000000000910190815220895191166020820190815273ffffffffffffffffffffffffffffffffffffffff959095166024820152604480820193909352918252606482612afb565b51925af13d156130c5573d67ffffffffffffffff8111612b3c5782519061301f601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200183612afb565b81523d6000602083013e5b81613096575b50156130395750565b606490517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f42726f776e466956323a205452414e534645525f4641494c45440000000000006044820152fd5b80518015925082156130ab575b505038613030565b6130be9250602080918301019101612c38565b38806130a3565b606061302a565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906040517f67cc3403000000000000000000000000000000000000000000000000000000008152602081600481865afa90811561324957600091613289575b506005546040517ffc3d545d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101829052602081604481875afa90811561324957600091613255575b506006546040517ffc3d545d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101929092529260209082908180604481015b03915afa9081156132495760009161321a575090565b90506020813d602011613241575b8161323560209383612afb565b810103126102e4575190565b3d9150613228565b6040513d6000823e3d90fd5b90506020813d602011613281575b8161327060209383612afb565b810103126102e457516132046131a8565b3d9150613263565b906020823d6020116132b3575b816132a360209383612afb565b8101031261033a57505138613142565b3d9150613296565b91908201809211612cc257565b6132f7846132f1856132eb61268061332a969a999a60ff60055460a01c166137bd565b95612d0b565b93612d0b565b808310801593916133169161338d576133108184612cb5565b926132bb565b9067ffffffffffffffff6009541690613557565b9182680100000000000000000192836801000000000000000011612cc257680100000000000000000391680100000000000000008311612cc257156133805761337d9291613377916134e0565b936134e0565b90565b61337d92613377916134e0565b6133108382612cb5565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6305f5e1008209916305f5e10082029182808510940393808503941461343b57838211156102e4576305f5e100829109818060000316809204600281600302188082026002030280820260020302808202600203028082026002030280820260020302809102600203029360018380600003040190848311900302920304170290565b50809250156102e4570490565b9190916000907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84820990848102928380841093039280840393146134d157826305f5e100111561033a57507facbe0e98f503f8881186e60dbb7f727bf36b7213ee9f5a78c767074b22e90e2193946305f5e100910990828211900360f81b910360081c170290565b5050506305f5e1009192500490565b6000917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818309918181029384808510940393808503941461354d578368010000000000000000111561033a57509068010000000000000000910990828211900360c01b910360401c1790565b5050505060401c90565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82840992828102928380861095039480860395146135ef57848311156102e457829109818060000316809204600281600302188082026002030280820260020302808202600203028082026002030280820260020302809102600203029360018380600003040190848311900302920304170290565b5050809250156102e4570490565b6dffffffffffffffffffffffffffff8111158061370f575b156136b1577f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1916dffffffffffffffffffffffffffff806040931691827bffffffffffffffffffffffffffff00000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000004260e01b169260701b16171780600755835192835260701c166020820152a1565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f42726f776e466956323a204f564552464c4f57000000000000000000000000006044820152fd5b506dffffffffffffffffffffffffffff821115613615565b906115ef61337d926113d061378e6113d061376b6007546dffffffffffffffffffffffffffff8116916dffffffffffffffffffffffffffff8260701c169160e01c90565b5092906dffffffffffffffffffffffffffff60ff60055460a01c169116906137bd565b916dffffffffffffffffffffffffffff60ff60065460a01c169116906137bd565b604d8111612cc257600a0a90565b60009060ff16601281111561380e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee9150019060ff8211612cc25761380860ff61337d93166137af565b90612d9c565b6012039060ff821161383157509061382b60ff61337d93166137af565b90612d0b565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602073ffffffffffffffffffffffffffffffffffffffff6000936138a4868654613a39565b85551693848452600182526138bd816040862054613a39565b858552600183526040852055604051908152a3565b602073ffffffffffffffffffffffffffffffffffffffff807f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925931693846000526002835260406000208282166000528352856040600020556040519586521693a3565b91906139419083612cb5565b91821161394a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f7700000000000000000000006044820152fd5b602073ffffffffffffffffffffffffffffffffffffffff807fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef93169384600052600183526139fb86604060002054613935565b856000526001845260406000205516938460005260018252613a2281604060002054613a39565b8560005260018352604060002055604051908152a3565b9190613a4590836132bb565b918210613a4e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f770000000000000000000000006044820152fdfea26469706673582212201634120ea8a3571b194d610828716ad7c6c5e7329387eff50ccf0bdb13b8557b64736f6c634300081c0033a264697066735822122035f522e0dab5d23d6b4b333f20f840c30daaef0d2b6228a20897e541397bab0164736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003f0bbeedea5e5f63a14cbda82718d4f25501fbea00000000000000000000000068bc42f886ddf6a4b0b90a9496493da1f8304536
-----Decoded View---------------
Arg [0] : _initialOracle (address): 0x3F0bBeEdEa5E5F63a14cBdA82718d4f25501fBeA
Arg [1] : _initialManager (address): 0x68bc42F886ddf6a4b0B90a9496493dA1f8304536
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000003f0bbeedea5e5f63a14cbda82718d4f25501fbea
Arg [1] : 00000000000000000000000068bc42f886ddf6a4b0b90a9496493da1f8304536
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.