Token UTU Trust Token
Overview ERC-20
Price
$0.00 @ 0.000000 MATIC
Fully Diluted Market Cap
Total Supply:
62,160,660 UTT
Holders:
6,106 addresses
Transfers:
-
Contract:
Decimals:
0
[ Download CSV Export ]
[ Download CSV Export ]
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
UTT
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol"; import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol"; contract UTT is ERC20Burnable, ERC20Pausable, Ownable, ChainlinkClient { using Chainlink for Chainlink.Request; /** * The `socialConnections` mapping is storing the connected socialIds * as so: address => socialTypeId => socialUserIdHash */ mapping (address => mapping (uint256 => bytes32) ) socialConnections; /** * The `socialConnectionReward` variable is the amount of tokens to be minted * as a reward for connecting/verifying with a social platform user id. */ uint256 public socialConnectionReward = 10000; // Reward parameters: /** New stake offset (see whitepaper) */ uint256 public O_n = 1; /** Discounting component for the new stake (see whitepaper) */ uint256 public D_n = 30; /** Discounting component for the stake of first-level previous endorsers (see whitepaper) */ uint256 public D_lvl1 = 2; /** Discounting component for the stake of second-level previous endorsers (see whitepaper) */ uint256 public D_lvl2 = 20; // /** Discounting component for other previous endorsers' total stake (see whitepaper) */ uint256 public D_o = 5000; // Keeping track of stakes on endorsements: /** A map targetAddress => endorserAddress => stake mapping all endorser's stakes by their endorsement target */ mapping (address => mapping(address => uint256)) public previousEndorserStakes; /** A map targetAddress => stake with the total stake by target */ mapping (address => uint) public totalStake; // Oracle related: /** * Chainlinkg orcale request data structure */ struct OracleRequest { address from; address target; uint256 amount; string transactionId; } /** Sent oracle requests by id */ mapping (bytes32 => OracleRequest) private oracleRequests; /** Address of the Chainlink oracle operator contract */ address private oracle; /** Id for oracle jobs from this contract */ bytes32 private jobId; /** LINK fee to be paid to the oracle operator contract for each request */ uint256 private fee; /** Contract migration flag; when migrating any further endorsements or social connections are disabled. */ bool public isMigrating; // Events for connecting social media accounts/other user ids. /** Social media account was connected */ event AddConnection(address indexed _user, uint indexed _connectedTypeId, bytes32 indexed _connectedUserIdHash); /** Social media account was disconnected */ event RemoveConnection(address indexed _user, uint indexed _connectedTypeId, bytes32 indexed _connectedUserIdHash); // Events for endorsements. /** A new endorsement was made */ event Endorse(address indexed _from, address indexed _to, uint _value, string _transactionId); /** A first-level previous endorser was rewarded */ event RewardPreviousEndorserLevel1(address endorser, uint256 reward); /** A second-level previous endorser was rewarded */ event RewardPreviousEndorserLevel2(address endorser, uint256 reward); /** * Constructs new UTU Trust Token contract. * See also {ERC20-constructor}. * @param _mintAmount amount of UTT minted to the deploying address; only used in testing. * @param _oracle Chainlink oracle operator contract address * @param _jobId Id for oracle jobs from this contract * @param _fee Initial value for the LINK fee * @param _link LINK token address */ constructor( uint256 _mintAmount, address _oracle, string memory _jobId, uint256 _fee, address _link ) ERC20("UTU Trust Token", "UTT") { _mint(msg.sender, _mintAmount); setChainlinkToken(_link); oracle = _oracle; jobId = stringToBytes32(_jobId); fee = _fee; } /** * Requires that the contract is not migrating. */ modifier notMigrating() { require(!isMigrating, "Contract is migrating"); _; } /** * Pauses all token transfers. * * See {ERC20Pausable} and {Pausable-_pause}. * */ function pause() public virtual onlyOwner { _pause(); } /** * Unpauses all token transfers. * * See {ERC20Pausable} and {Pausable-_unpause}. * */ function unpause() public virtual onlyOwner { _unpause(); } /** * Returns 0 decimals (since we don't need decimals for this particular use case). */ function decimals() public view virtual override returns (uint8) { return 0; } // Governance functions for setting the reward and penalty parameters /** Sets the O_n reward formula parameter */ function setO_n(uint256 val) public onlyOwner { O_n = val; } /** Sets the D_n reward formula parameter */ function setD_n(uint256 val) public onlyOwner { D_n = val; } /** Sets the D_lvl1 reward formula parameter */ function setD_lvl1(uint256 val) public onlyOwner { D_lvl1 = val; } /** Sets the D_lvl2 reward formula parameter */ function setD_lvl2(uint256 val) public onlyOwner { D_lvl2 = val; } /** Sets the D_o reward formula parameter */ function setD_o(uint256 val) public onlyOwner { D_o = val; } /** Sets the LINK fee to be paid for each request */ function setFee(uint256 _fee) public onlyOwner { fee = _fee; } /** * @dev Computes the reward to be given to previousEndorser for a new endorsement of s_n on the given target and the * previous endorser level-dependent discount D_lvl_p. It assumes that the new endorsement s_n has not yet been * added to the totalStake map. * See whitepaper. * @param target the endorsed entity (address is just used as an id here) * @param previousEndorser address of the previous endorser for whom the reward shall be computed * @param D_lvl_p Discounting factor for the level of the previous endorser (i.e. value of D_lvl1 or D_lvl2) * @param s_n stake for the new endorsement * @return The reward in UTT that shall be minted to previousEndorser */ function computeReward( address target, address previousEndorser, uint256 D_lvl_p, uint256 s_n ) private view returns (uint256) { uint256 s_p = previousEndorserStakes[target][previousEndorser]; uint256 s_o = totalStake[target] - s_p; return (s_p * (s_n + O_n) * D_o) / (D_lvl_p * (s_n + D_n) * (D_o + s_o)); } /** * @dev Called from fulfillEndorse, which is called by the oracle operator contract when the oracle has retrieved * previous endorsers from the UTU Trust API. It computes the rewards for each previous endorser according to their * levels, and adds the new stake to the totalStake and previousEndorserStakes maps. * @param from new endorser's address * @param target the endorsed entity (address is just used as an id here) * @param amount the stake for the new endorsement * @param transactionId an id representing the "business transaction" for which the endorsement was made; this is _not_ necessarily an Ethereum transaction id. * @param endorsersLevel1 list of first-level previous endorser addresses. * @param endorsersLevel2 list of second-level previous endorser addresses. * Invokes `super._transfer()`. */ function _endorse( address from, address target, uint256 amount, string memory transactionId, address[] memory endorsersLevel1, address[] memory endorsersLevel2 ) internal { //reward first-level previous endorsers for(uint8 i=0; i < endorsersLevel1.length; i++){ uint256 endorserReward = computeReward(target, endorsersLevel1[i], D_lvl1, amount); // mint rewarded tokens to endorser super._mint(address(endorsersLevel1[i]), endorserReward); emit RewardPreviousEndorserLevel1(endorsersLevel1[i], endorserReward); } //reward first-level previous endorsers for(uint8 i=0; i < endorsersLevel2.length; i++){ uint256 endorserReward = computeReward(target, endorsersLevel2[i], D_lvl2, amount); // mint rewarded tokens to endorser super._mint(endorsersLevel2[i], endorserReward); emit RewardPreviousEndorserLevel2(endorsersLevel2[i], endorserReward); } totalStake[target] += amount; previousEndorserStakes[target][from] += amount; emit Endorse(from, target, amount, transactionId); } /** * @notice Creates a new staked endorsement, where the caller is the endorser. Previous endorsers, retrieved * from the UTU Trust API via an oracle, will be rewarded according to the reward formula from the * whitepaper. * @dev This creates an oracle request. The actual endorsement, staking and rewarding is done on its fulfillment. * @param target the endorsed entity (address is just used as an id here) * @param amount the stake for the new endorsement * @param transactionId an id representing the "business transaction" for which the endorsement was made; this is * _not_ necessarily an Ethereum transaction id. */ function endorse(address target, uint256 amount, string memory transactionId) notMigrating external { require(msg.sender == tx.origin, "should be an user"); uint256 fromBalance = balanceOf(msg.sender); require(fromBalance >= amount, "UTT: endorse amount exceeds balance"); Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfillEndorse.selector); request.add("targetAddress", addressToString(target)); request.add("sourceAddress", addressToString(msg.sender)); request.add("transactionId", transactionId); bytes32 requestId = sendOperatorRequestTo(oracle, request, fee); oracleRequests[requestId] = OracleRequest({ from: msg.sender, target: target, amount: amount, transactionId: transactionId }); } /** * @dev Called back from the oracle operator contract when the oracle request was fulfilled, with the retrieved * values. * @param _requestId oracle request id as it was stored in oracleRequests * @param endorsersLevel1 list of first-level previous endorser addresses * @param endorsersLevel2 list of second-level previous endorser addresses */ function fulfillEndorse( bytes32 _requestId, address[] calldata endorsersLevel1, address[] calldata endorsersLevel2 ) external recordChainlinkFulfillment(_requestId) { OracleRequest memory r = oracleRequests[_requestId]; require(r.target != address(0), "unknown endorsment"); _burn(r.from, r.amount); _endorse(r.from, r.target, r.amount, r.transactionId, endorsersLevel1, endorsersLevel2); } /** * @dev Called by UTU's social media connector when the user connects a supported social media account, and rewards * them for it with a configured amount of UTT. It's callable only by owner to prevent calls for which the * connector hasn't verified that the connection was really made, and to prevent repeated dis/-reconnects * (this might be solved differently in the future). * @param user the connecting user's address * @param connectedTypeId id of the social media platform; we allow a user to connect a particular platform only * once. * @param connectedUserIdHash hash of the user account id or name; this value is hashed to preserve the user's * privacy. */ function addConnection( address user, uint256 connectedTypeId, bytes32 connectedUserIdHash ) public notMigrating onlyOwner { // only add connection if not previously added if (socialConnections[user][connectedTypeId] == 0) { socialConnections[user][connectedTypeId] = connectedUserIdHash; // mint reward super._mint(user, socialConnectionReward); emit AddConnection(user, connectedTypeId, connectedUserIdHash); } } /** * @dev Called by UTU's social media connector when the user removes a connection to a social media account. It's * callable only by owner to prevent repeated dis/-reconnects (this might be solved differently in the future). * @param user the connecting user's address * @param connectedTypeId id of the social media platform */ function removeConnection( address user, uint256 connectedTypeId ) public notMigrating onlyOwner { // only remove connection if currently connected if (socialConnections[user][connectedTypeId] != 0) { socialConnections[user][connectedTypeId] = 0; emit RemoveConnection(user, connectedTypeId, 0); } } /** * Sets the amount of UTT to be rewarded for (new) social media connections * @param amount of UTT to be rewarded for (new) social media connections */ function setSocialConnectionReward( uint256 amount ) public onlyOwner { socialConnectionReward = amount; } /** * @dev just calls super._beforeTokenTransfer() */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal override(ERC20, ERC20Pausable) { super._beforeTokenTransfer(from, to, amount); } /** * Always reverts on external calls on transfer, since UTT is not transferable. */ function transfer(address recipient, uint256 amount) public pure override returns (bool) { revert('Not allowed.'); } /** * * Always reverts on external calls on approve, since UTT is not transferable. */ function approve(address spender, uint256 amount) public pure override returns (bool) { revert('Not allowed.'); } /** * @dev Converts an address to a string "0x..." representation. * @param x an address * @return string representation of the address */ function addressToString(address x) internal pure returns (string memory) { bytes memory s = new bytes(40); for (uint i = 0; i < 20; i++) { bytes1 b = bytes1(uint8(uint(uint160(x)) / (2**(8*(19 - i))))); bytes1 hi = bytes1(uint8(b) / 16); bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); s[2*i] = char(hi); s[2*i+1] = char(lo); } return string(abi.encodePacked("0x", string(s))); } /** * @dev Converts a byte value to its readable char value.@param * @param b byte value * @return c the value as a readable char */ function char(bytes1 b) internal pure returns (bytes1 c) { if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); else return bytes1(uint8(b) + 0x57); } /** * @dev Converts a string to a bytes32 representation * @param source a string * @return result a bytes32 */ function stringToBytes32(string memory source) public pure returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(source); if (tempEmptyStringTest.length == 0) { return 0x0; } assembly { result := mload(add(source, 32)) } } /** * Toggles the migration flag. While migrating, no new endorsements or social media (dis)connections can be made. * @dev Endorsements can still be fulfilled; thus the actual migration process should not be started until * all pending fulfillments are done. */ function toggleMigrationFlag() public onlyOwner { isMigrating = !isMigrating; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../ERC20.sol"; import "../../../utils/Context.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public virtual { _burn(_msgSender(), amount); } /** * @dev Destroys `amount` tokens from `account`, deducting from the caller's * allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { uint256 currentAllowance = allowance(account, _msgSender()); require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance"); unchecked { _approve(account, _msgSender(), currentAllowance - amount); } _burn(account, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../ERC20.sol"; import "../../../security/Pausable.sol"; /** * @dev ERC20 token with pausable token transfers, minting and burning. * * Useful for scenarios such as preventing trades until the end of an evaluation * period, or having an emergency switch for freezing all token transfers in the * event of a large bug. */ abstract contract ERC20Pausable is ERC20, Pausable { /** * @dev See {ERC20-_beforeTokenTransfer}. * * Requirements: * * - the contract must not be paused. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual override { super._beforeTokenTransfer(from, to, amount); require(!paused(), "ERC20Pausable: token transfer while paused"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Chainlink.sol"; import "./interfaces/ENSInterface.sol"; import "./interfaces/LinkTokenInterface.sol"; import "./interfaces/ChainlinkRequestInterface.sol"; import "./interfaces/OperatorInterface.sol"; import "./interfaces/PointerInterface.sol"; import {ENSResolver as ENSResolver_Chainlink} from "./vendor/ENSResolver.sol"; /** * @title The ChainlinkClient contract * @notice Contract writers can inherit this contract in order to create requests for the * Chainlink network */ abstract contract ChainlinkClient { using Chainlink for Chainlink.Request; uint256 internal constant LINK_DIVISIBILITY = 10**18; uint256 private constant AMOUNT_OVERRIDE = 0; address private constant SENDER_OVERRIDE = address(0); uint256 private constant ORACLE_ARGS_VERSION = 1; uint256 private constant OPERATOR_ARGS_VERSION = 2; bytes32 private constant ENS_TOKEN_SUBNAME = keccak256("link"); bytes32 private constant ENS_ORACLE_SUBNAME = keccak256("oracle"); address private constant LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571; ENSInterface private s_ens; bytes32 private s_ensNode; LinkTokenInterface private s_link; OperatorInterface private s_oracle; uint256 private s_requestCount = 1; mapping(bytes32 => address) private s_pendingRequests; event ChainlinkRequested(bytes32 indexed id); event ChainlinkFulfilled(bytes32 indexed id); event ChainlinkCancelled(bytes32 indexed id); /** * @notice Creates a request that can hold additional parameters * @param specId The Job Specification ID that the request will be created for * @param callbackAddr address to operate the callback on * @param callbackFunctionSignature function signature to use for the callback * @return A Chainlink Request struct in memory */ function buildChainlinkRequest( bytes32 specId, address callbackAddr, bytes4 callbackFunctionSignature ) internal pure returns (Chainlink.Request memory) { Chainlink.Request memory req; return req.initialize(specId, callbackAddr, callbackFunctionSignature); } /** * @notice Creates a request that can hold additional parameters * @param specId The Job Specification ID that the request will be created for * @param callbackFunctionSignature function signature to use for the callback * @return A Chainlink Request struct in memory */ function buildOperatorRequest(bytes32 specId, bytes4 callbackFunctionSignature) internal view returns (Chainlink.Request memory) { Chainlink.Request memory req; return req.initialize(specId, address(this), callbackFunctionSignature); } /** * @notice Creates a Chainlink request to the stored oracle address * @dev Calls `chainlinkRequestTo` with the stored oracle address * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function sendChainlinkRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) { return sendChainlinkRequestTo(address(s_oracle), req, payment); } /** * @notice Creates a Chainlink request to the specified oracle address * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to * send LINK which creates a request on the target oracle contract. * Emits ChainlinkRequested event. * @param oracleAddress The address of the oracle for the request * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function sendChainlinkRequestTo( address oracleAddress, Chainlink.Request memory req, uint256 payment ) internal returns (bytes32 requestId) { uint256 nonce = s_requestCount; s_requestCount = nonce + 1; bytes memory encodedRequest = abi.encodeWithSelector( ChainlinkRequestInterface.oracleRequest.selector, SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent req.id, address(this), req.callbackFunctionId, nonce, ORACLE_ARGS_VERSION, req.buf.buf ); return _rawRequest(oracleAddress, nonce, payment, encodedRequest); } /** * @notice Creates a Chainlink request to the stored oracle address * @dev This function supports multi-word response * @dev Calls `sendOperatorRequestTo` with the stored oracle address * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function sendOperatorRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) { return sendOperatorRequestTo(address(s_oracle), req, payment); } /** * @notice Creates a Chainlink request to the specified oracle address * @dev This function supports multi-word response * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to * send LINK which creates a request on the target oracle contract. * Emits ChainlinkRequested event. * @param oracleAddress The address of the oracle for the request * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function sendOperatorRequestTo( address oracleAddress, Chainlink.Request memory req, uint256 payment ) internal returns (bytes32 requestId) { uint256 nonce = s_requestCount; s_requestCount = nonce + 1; bytes memory encodedRequest = abi.encodeWithSelector( OperatorInterface.operatorRequest.selector, SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent req.id, req.callbackFunctionId, nonce, OPERATOR_ARGS_VERSION, req.buf.buf ); return _rawRequest(oracleAddress, nonce, payment, encodedRequest); } /** * @notice Make a request to an oracle * @param oracleAddress The address of the oracle for the request * @param nonce used to generate the request ID * @param payment The amount of LINK to send for the request * @param encodedRequest data encoded for request type specific format * @return requestId The request ID */ function _rawRequest( address oracleAddress, uint256 nonce, uint256 payment, bytes memory encodedRequest ) private returns (bytes32 requestId) { requestId = keccak256(abi.encodePacked(this, nonce)); s_pendingRequests[requestId] = oracleAddress; emit ChainlinkRequested(requestId); require(s_link.transferAndCall(oracleAddress, payment, encodedRequest), "unable to transferAndCall to oracle"); } /** * @notice Allows a request to be cancelled if it has not been fulfilled * @dev Requires keeping track of the expiration value emitted from the oracle contract. * Deletes the request from the `pendingRequests` mapping. * Emits ChainlinkCancelled event. * @param requestId The request ID * @param payment The amount of LINK sent for the request * @param callbackFunc The callback function specified for the request * @param expiration The time of the expiration for the request */ function cancelChainlinkRequest( bytes32 requestId, uint256 payment, bytes4 callbackFunc, uint256 expiration ) internal { OperatorInterface requested = OperatorInterface(s_pendingRequests[requestId]); delete s_pendingRequests[requestId]; emit ChainlinkCancelled(requestId); requested.cancelOracleRequest(requestId, payment, callbackFunc, expiration); } /** * @notice the next request count to be used in generating a nonce * @dev starts at 1 in order to ensure consistent gas cost * @return returns the next request count to be used in a nonce */ function getNextRequestCount() internal view returns (uint256) { return s_requestCount; } /** * @notice Sets the stored oracle address * @param oracleAddress The address of the oracle contract */ function setChainlinkOracle(address oracleAddress) internal { s_oracle = OperatorInterface(oracleAddress); } /** * @notice Sets the LINK token address * @param linkAddress The address of the LINK token contract */ function setChainlinkToken(address linkAddress) internal { s_link = LinkTokenInterface(linkAddress); } /** * @notice Sets the Chainlink token address for the public * network as given by the Pointer contract */ function setPublicChainlinkToken() internal { setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress()); } /** * @notice Retrieves the stored address of the LINK token * @return The address of the LINK token */ function chainlinkTokenAddress() internal view returns (address) { return address(s_link); } /** * @notice Retrieves the stored address of the oracle contract * @return The address of the oracle contract */ function chainlinkOracleAddress() internal view returns (address) { return address(s_oracle); } /** * @notice Allows for a request which was created on another contract to be fulfilled * on this contract * @param oracleAddress The address of the oracle contract that will fulfill the request * @param requestId The request ID used for the response */ function addChainlinkExternalRequest(address oracleAddress, bytes32 requestId) internal notPendingRequest(requestId) { s_pendingRequests[requestId] = oracleAddress; } /** * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS * @dev Accounts for subnodes having different resolvers * @param ensAddress The address of the ENS contract * @param node The ENS node hash */ function useChainlinkWithENS(address ensAddress, bytes32 node) internal { s_ens = ENSInterface(ensAddress); s_ensNode = node; bytes32 linkSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_TOKEN_SUBNAME)); ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(linkSubnode)); setChainlinkToken(resolver.addr(linkSubnode)); updateChainlinkOracleWithENS(); } /** * @notice Sets the stored oracle contract with the address resolved by ENS * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously */ function updateChainlinkOracleWithENS() internal { bytes32 oracleSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_ORACLE_SUBNAME)); ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(oracleSubnode)); setChainlinkOracle(resolver.addr(oracleSubnode)); } /** * @notice Ensures that the fulfillment is valid for this contract * @dev Use if the contract developer prefers methods instead of modifiers for validation * @param requestId The request ID for fulfillment */ function validateChainlinkCallback(bytes32 requestId) internal recordChainlinkFulfillment(requestId) // solhint-disable-next-line no-empty-blocks { } /** * @dev Reverts if the sender is not the oracle of the request. * Emits ChainlinkFulfilled event. * @param requestId The request ID for fulfillment */ modifier recordChainlinkFulfillment(bytes32 requestId) { require(msg.sender == s_pendingRequests[requestId], "Source must be the oracle of the request"); delete s_pendingRequests[requestId]; emit ChainlinkFulfilled(requestId); _; } /** * @dev Reverts if the request is already pending * @param requestId The request ID for fulfillment */ modifier notPendingRequest(bytes32 requestId) { require(s_pendingRequests[requestId] == address(0), "Request is already pending"); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {CBORChainlink} from "./vendor/CBORChainlink.sol"; import {BufferChainlink} from "./vendor/BufferChainlink.sol"; /** * @title Library for common Chainlink functions * @dev Uses imported CBOR library for encoding to buffer */ library Chainlink { uint256 internal constant defaultBufferSize = 256; // solhint-disable-line const-name-snakecase using CBORChainlink for BufferChainlink.buffer; struct Request { bytes32 id; address callbackAddress; bytes4 callbackFunctionId; uint256 nonce; BufferChainlink.buffer buf; } /** * @notice Initializes a Chainlink request * @dev Sets the ID, callback address, and callback function signature on the request * @param self The uninitialized request * @param jobId The Job Specification ID * @param callbackAddr The callback address * @param callbackFunc The callback function signature * @return The initialized request */ function initialize( Request memory self, bytes32 jobId, address callbackAddr, bytes4 callbackFunc ) internal pure returns (Chainlink.Request memory) { BufferChainlink.init(self.buf, defaultBufferSize); self.id = jobId; self.callbackAddress = callbackAddr; self.callbackFunctionId = callbackFunc; return self; } /** * @notice Sets the data for the buffer without encoding CBOR on-chain * @dev CBOR can be closed with curly-brackets {} or they can be left off * @param self The initialized request * @param data The CBOR data */ function setBuffer(Request memory self, bytes memory data) internal pure { BufferChainlink.init(self.buf, data.length); BufferChainlink.append(self.buf, data); } /** * @notice Adds a string value to the request with a given key name * @param self The initialized request * @param key The name of the key * @param value The string value to add */ function add( Request memory self, string memory key, string memory value ) internal pure { self.buf.encodeString(key); self.buf.encodeString(value); } /** * @notice Adds a bytes value to the request with a given key name * @param self The initialized request * @param key The name of the key * @param value The bytes value to add */ function addBytes( Request memory self, string memory key, bytes memory value ) internal pure { self.buf.encodeString(key); self.buf.encodeBytes(value); } /** * @notice Adds a int256 value to the request with a given key name * @param self The initialized request * @param key The name of the key * @param value The int256 value to add */ function addInt( Request memory self, string memory key, int256 value ) internal pure { self.buf.encodeString(key); self.buf.encodeInt(value); } /** * @notice Adds a uint256 value to the request with a given key name * @param self The initialized request * @param key The name of the key * @param value The uint256 value to add */ function addUint( Request memory self, string memory key, uint256 value ) internal pure { self.buf.encodeString(key); self.buf.encodeUInt(value); } /** * @notice Adds an array of strings to the request with a given key name * @param self The initialized request * @param key The name of the key * @param values The array of string values to add */ function addStringArray( Request memory self, string memory key, string[] memory values ) internal pure { self.buf.encodeString(key); self.buf.startArray(); for (uint256 i = 0; i < values.length; i++) { self.buf.encodeString(values[i]); } self.buf.endSequence(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ENSInterface { // Logged when the owner of a node assigns a new owner to a subnode. event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); // Logged when the owner of a node transfers ownership to a new account. event Transfer(bytes32 indexed node, address owner); // Logged when the resolver for a node changes. event NewResolver(bytes32 indexed node, address resolver); // Logged when the TTL of a node changes event NewTTL(bytes32 indexed node, uint64 ttl); function setSubnodeOwner( bytes32 node, bytes32 label, address owner ) external; function setResolver(bytes32 node, address resolver) external; function setOwner(bytes32 node, address owner) external; function setTTL(bytes32 node, uint64 ttl) external; function owner(bytes32 node) external view returns (address); function resolver(bytes32 node) external view returns (address); function ttl(bytes32 node) external view returns (uint64); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface LinkTokenInterface { function allowance(address owner, address spender) external view returns (uint256 remaining); function approve(address spender, uint256 value) external returns (bool success); function balanceOf(address owner) external view returns (uint256 balance); function decimals() external view returns (uint8 decimalPlaces); function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); function increaseApproval(address spender, uint256 subtractedValue) external; function name() external view returns (string memory tokenName); function symbol() external view returns (string memory tokenSymbol); function totalSupply() external view returns (uint256 totalTokensIssued); function transfer(address to, uint256 value) external returns (bool success); function transferAndCall( address to, uint256 value, bytes calldata data ) external returns (bool success); function transferFrom( address from, address to, uint256 value ) external returns (bool success); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ChainlinkRequestInterface { function oracleRequest( address sender, uint256 requestPrice, bytes32 serviceAgreementID, address callbackAddress, bytes4 callbackFunctionId, uint256 nonce, uint256 dataVersion, bytes calldata data ) external; function cancelOracleRequest( bytes32 requestId, uint256 payment, bytes4 callbackFunctionId, uint256 expiration ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./OracleInterface.sol"; import "./ChainlinkRequestInterface.sol"; interface OperatorInterface is OracleInterface, ChainlinkRequestInterface { function operatorRequest( address sender, uint256 payment, bytes32 specId, bytes4 callbackFunctionId, uint256 nonce, uint256 dataVersion, bytes calldata data ) external; function fulfillOracleRequest2( bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data ) external returns (bool); function ownerTransferAndCall( address to, uint256 value, bytes calldata data ) external returns (bool success); function distributeFunds(address payable[] calldata receivers, uint256[] calldata amounts) external payable; function getAuthorizedSenders() external returns (address[] memory); function setAuthorizedSenders(address[] calldata senders) external; function getForwarder() external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface PointerInterface { function getAddress() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; abstract contract ENSResolver { function addr(bytes32 node) public view virtual returns (address); }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.19; import {BufferChainlink} from "./BufferChainlink.sol"; library CBORChainlink { using BufferChainlink for BufferChainlink.buffer; uint8 private constant MAJOR_TYPE_INT = 0; uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; uint8 private constant MAJOR_TYPE_BYTES = 2; uint8 private constant MAJOR_TYPE_STRING = 3; uint8 private constant MAJOR_TYPE_ARRAY = 4; uint8 private constant MAJOR_TYPE_MAP = 5; uint8 private constant MAJOR_TYPE_TAG = 6; uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; uint8 private constant TAG_TYPE_BIGNUM = 2; uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3; function encodeFixedNumeric(BufferChainlink.buffer memory buf, uint8 major, uint64 value) private pure { if(value <= 23) { buf.appendUint8(uint8((major << 5) | value)); } else if (value <= 0xFF) { buf.appendUint8(uint8((major << 5) | 24)); buf.appendInt(value, 1); } else if (value <= 0xFFFF) { buf.appendUint8(uint8((major << 5) | 25)); buf.appendInt(value, 2); } else if (value <= 0xFFFFFFFF) { buf.appendUint8(uint8((major << 5) | 26)); buf.appendInt(value, 4); } else { buf.appendUint8(uint8((major << 5) | 27)); buf.appendInt(value, 8); } } function encodeIndefiniteLengthType(BufferChainlink.buffer memory buf, uint8 major) private pure { buf.appendUint8(uint8((major << 5) | 31)); } function encodeUInt(BufferChainlink.buffer memory buf, uint value) internal pure { if(value > 0xFFFFFFFFFFFFFFFF) { encodeBigNum(buf, value); } else { encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value)); } } function encodeInt(BufferChainlink.buffer memory buf, int value) internal pure { if(value < -0x10000000000000000) { encodeSignedBigNum(buf, value); } else if(value > 0xFFFFFFFFFFFFFFFF) { encodeBigNum(buf, uint(value)); } else if(value >= 0) { encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(uint256(value))); } else { encodeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(uint256(-1 - value))); } } function encodeBytes(BufferChainlink.buffer memory buf, bytes memory value) internal pure { encodeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length)); buf.append(value); } function encodeBigNum(BufferChainlink.buffer memory buf, uint value) internal pure { buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM)); encodeBytes(buf, abi.encode(value)); } function encodeSignedBigNum(BufferChainlink.buffer memory buf, int input) internal pure { buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM)); encodeBytes(buf, abi.encode(uint256(-1 - input))); } function encodeString(BufferChainlink.buffer memory buf, string memory value) internal pure { encodeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length)); buf.append(bytes(value)); } function startArray(BufferChainlink.buffer memory buf) internal pure { encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); } function startMap(BufferChainlink.buffer memory buf) internal pure { encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); } function endSequence(BufferChainlink.buffer memory buf) internal pure { encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev A library for working with mutable byte buffers in Solidity. * * Byte buffers are mutable and expandable, and provide a variety of primitives * for writing to them. At any time you can fetch a bytes object containing the * current contents of the buffer. The bytes object should not be stored between * operations, as it may change due to resizing of the buffer. */ library BufferChainlink { /** * @dev Represents a mutable buffer. Buffers have a current value (buf) and * a capacity. The capacity may be longer than the current value, in * which case it can be extended without the need to allocate more memory. */ struct buffer { bytes buf; uint256 capacity; } /** * @dev Initializes a buffer with an initial capacity. * @param buf The buffer to initialize. * @param capacity The number of bytes of space to allocate the buffer. * @return The buffer, for chaining. */ function init(buffer memory buf, uint256 capacity) internal pure returns (buffer memory) { if (capacity % 32 != 0) { capacity += 32 - (capacity % 32); } // Allocate space for the buffer data buf.capacity = capacity; assembly { let ptr := mload(0x40) mstore(buf, ptr) mstore(ptr, 0) mstore(0x40, add(32, add(ptr, capacity))) } return buf; } /** * @dev Initializes a new buffer from an existing bytes object. * Changes to the buffer may mutate the original value. * @param b The bytes object to initialize the buffer with. * @return A new buffer. */ function fromBytes(bytes memory b) internal pure returns (buffer memory) { buffer memory buf; buf.buf = b; buf.capacity = b.length; return buf; } function resize(buffer memory buf, uint256 capacity) private pure { bytes memory oldbuf = buf.buf; init(buf, capacity); append(buf, oldbuf); } function max(uint256 a, uint256 b) private pure returns (uint256) { if (a > b) { return a; } return b; } /** * @dev Sets buffer length to 0. * @param buf The buffer to truncate. * @return The original buffer, for chaining.. */ function truncate(buffer memory buf) internal pure returns (buffer memory) { assembly { let bufptr := mload(buf) mstore(bufptr, 0) } return buf; } /** * @dev Writes a byte string to a buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param off The start offset to write to. * @param data The data to append. * @param len The number of bytes to copy. * @return The original buffer, for chaining. */ function write( buffer memory buf, uint256 off, bytes memory data, uint256 len ) internal pure returns (buffer memory) { require(len <= data.length); if (off + len > buf.capacity) { resize(buf, max(buf.capacity, len + off) * 2); } uint256 dest; uint256 src; assembly { // Memory address of the buffer data let bufptr := mload(buf) // Length of existing buffer data let buflen := mload(bufptr) // Start address = buffer address + offset + sizeof(buffer length) dest := add(add(bufptr, 32), off) // Update buffer length if we're extending it if gt(add(len, off), buflen) { mstore(bufptr, add(len, off)) } src := add(data, 32) } // Copy word-length chunks while possible for (; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes unchecked { uint256 mask = (256**(32 - len)) - 1; assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } return buf; } /** * @dev Appends a byte string to a buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @param len The number of bytes to copy. * @return The original buffer, for chaining. */ function append( buffer memory buf, bytes memory data, uint256 len ) internal pure returns (buffer memory) { return write(buf, buf.buf.length, data, len); } /** * @dev Appends a byte string to a buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { return write(buf, buf.buf.length, data, data.length); } /** * @dev Writes a byte to the buffer. Resizes if doing so would exceed the * capacity of the buffer. * @param buf The buffer to append to. * @param off The offset to write the byte at. * @param data The data to append. * @return The original buffer, for chaining. */ function writeUint8( buffer memory buf, uint256 off, uint8 data ) internal pure returns (buffer memory) { if (off >= buf.capacity) { resize(buf, buf.capacity * 2); } assembly { // Memory address of the buffer data let bufptr := mload(buf) // Length of existing buffer data let buflen := mload(bufptr) // Address = buffer address + sizeof(buffer length) + off let dest := add(add(bufptr, off), 32) mstore8(dest, data) // Update buffer length if we extended it if eq(off, buflen) { mstore(bufptr, add(buflen, 1)) } } return buf; } /** * @dev Appends a byte to the buffer. Resizes if doing so would exceed the * capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function appendUint8(buffer memory buf, uint8 data) internal pure returns (buffer memory) { return writeUint8(buf, buf.buf.length, data); } /** * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would * exceed the capacity of the buffer. * @param buf The buffer to append to. * @param off The offset to write at. * @param data The data to append. * @param len The number of bytes to write (left-aligned). * @return The original buffer, for chaining. */ function write( buffer memory buf, uint256 off, bytes32 data, uint256 len ) private pure returns (buffer memory) { if (len + off > buf.capacity) { resize(buf, (len + off) * 2); } unchecked { uint256 mask = (256**len) - 1; // Right-align data data = data >> (8 * (32 - len)); assembly { // Memory address of the buffer data let bufptr := mload(buf) // Address = buffer address + sizeof(buffer length) + off + len let dest := add(add(bufptr, off), len) mstore(dest, or(and(mload(dest), not(mask)), data)) // Update buffer length if we extended it if gt(add(off, len), mload(bufptr)) { mstore(bufptr, add(off, len)) } } } return buf; } /** * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the * capacity of the buffer. * @param buf The buffer to append to. * @param off The offset to write at. * @param data The data to append. * @return The original buffer, for chaining. */ function writeBytes20( buffer memory buf, uint256 off, bytes20 data ) internal pure returns (buffer memory) { return write(buf, off, bytes32(data), 20); } /** * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chhaining. */ function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { return write(buf, buf.buf.length, bytes32(data), 20); } /** * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { return write(buf, buf.buf.length, data, 32); } /** * @dev Writes an integer to the buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param off The offset to write at. * @param data The data to append. * @param len The number of bytes to write (right-aligned). * @return The original buffer, for chaining. */ function writeInt( buffer memory buf, uint256 off, uint256 data, uint256 len ) private pure returns (buffer memory) { if (len + off > buf.capacity) { resize(buf, (len + off) * 2); } uint256 mask = (256**len) - 1; assembly { // Memory address of the buffer data let bufptr := mload(buf) // Address = buffer address + off + sizeof(buffer length) + len let dest := add(add(bufptr, off), len) mstore(dest, or(and(mload(dest), not(mask)), data)) // Update buffer length if we extended it if gt(add(off, len), mload(bufptr)) { mstore(bufptr, add(off, len)) } } return buf; } /** * @dev Appends a byte to the end of the buffer. Resizes if doing so would * exceed the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer. */ function appendInt( buffer memory buf, uint256 data, uint256 len ) internal pure returns (buffer memory) { return writeInt(buf, buf.buf.length, data, len); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface OracleInterface { function fulfillOracleRequest( bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes32 data ) external returns (bool); function isAuthorizedSender(address node) external view returns (bool); function withdraw(address recipient, uint256 amount) external; function withdrawable() external view returns (uint256); }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"string","name":"_jobId","type":"string"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"address","name":"_link","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"uint256","name":"_connectedTypeId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"_connectedUserIdHash","type":"bytes32"}],"name":"AddConnection","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"ChainlinkCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"ChainlinkFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"ChainlinkRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"},{"indexed":false,"internalType":"string","name":"_transactionId","type":"string"}],"name":"Endorse","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"uint256","name":"_connectedTypeId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"_connectedUserIdHash","type":"bytes32"}],"name":"RemoveConnection","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"endorser","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPreviousEndorserLevel1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"endorser","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPreviousEndorserLevel2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"D_lvl1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"D_lvl2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"D_n","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"D_o","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"O_n","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"connectedTypeId","type":"uint256"},{"internalType":"bytes32","name":"connectedUserIdHash","type":"bytes32"}],"name":"addConnection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"transactionId","type":"string"}],"name":"endorse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_requestId","type":"bytes32"},{"internalType":"address[]","name":"endorsersLevel1","type":"address[]"},{"internalType":"address[]","name":"endorsersLevel2","type":"address[]"}],"name":"fulfillEndorse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isMigrating","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"previousEndorserStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"connectedTypeId","type":"uint256"}],"name":"removeConnection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"name":"setD_lvl1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"name":"setD_lvl2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"name":"setD_n","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"name":"setD_o","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"name":"setO_n","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setSocialConnectionReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"socialConnectionReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"source","type":"string"}],"name":"stringToBytes32","outputs":[{"internalType":"bytes32","name":"result","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleMigrationFlag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526001600a55612710600d556001600e55601e600f55600260105560146011556113886012553480156200003657600080fd5b5060405162005f7e38038062005f7e83398181016040528101906200005c919062000685565b6040518060400160405280600f81526020017f55545520547275737420546f6b656e00000000000000000000000000000000008152506040518060400160405280600381526020017f55545400000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000e092919062000529565b508060049080519060200190620000f992919062000529565b5050506000600560006101000a81548160ff021916908315150217905550620001376200012b620001c460201b60201c565b620001cc60201b60201c565b6200014933866200029260201b60201c565b6200015a816200040b60201b60201c565b83601660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ac836200044f60201b60201c565b60178190555081601881905550505050505062000af7565b600033905090565b6000600560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141562000305576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002fc906200078b565b60405180910390fd5b62000319600083836200047b60201b60201c565b80600260008282546200032d91906200085c565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546200038491906200085c565b925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051620003eb9190620007cf565b60405180910390a362000407600083836200049860201b60201c565b5050565b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000808290506000815114156200046d576000801b91505062000476565b60208301519150505b919050565b620004938383836200049d60201b62001f681760201c565b505050565b505050565b620004b58383836200050d60201b62001fc01760201c565b620004c56200051260201b60201c565b1562000508576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004ff90620007ad565b60405180910390fd5b505050565b505050565b6000600560009054906101000a900460ff16905090565b82805462000537906200092d565b90600052602060002090601f0160209004810192826200055b5760008555620005a7565b82601f106200057657805160ff1916838001178555620005a7565b82800160010185558215620005a7579182015b82811115620005a657825182559160200191906001019062000589565b5b509050620005b69190620005ba565b5090565b5b80821115620005d5576000816000905550600101620005bb565b5090565b6000620005f0620005ea8462000815565b620007ec565b9050828152602081018484840111156200060f576200060e62000a2b565b5b6200061c848285620008f7565b509392505050565b600081519050620006358162000ac3565b92915050565b600082601f83011262000653576200065262000a26565b5b815162000665848260208601620005d9565b91505092915050565b6000815190506200067f8162000add565b92915050565b600080600080600060a08688031215620006a457620006a362000a35565b5b6000620006b4888289016200066e565b9550506020620006c78882890162000624565b945050604086015167ffffffffffffffff811115620006eb57620006ea62000a30565b5b620006f9888289016200063b565b93505060606200070c888289016200066e565b92505060806200071f8882890162000624565b9150509295509295909350565b60006200073b601f836200084b565b9150620007488262000a4b565b602082019050919050565b600062000762602a836200084b565b91506200076f8262000a74565b604082019050919050565b6200078581620008ed565b82525050565b60006020820190508181036000830152620007a6816200072c565b9050919050565b60006020820190508181036000830152620007c88162000753565b9050919050565b6000602082019050620007e660008301846200077a565b92915050565b6000620007f86200080b565b905062000806828262000963565b919050565b6000604051905090565b600067ffffffffffffffff821115620008335762000832620009f7565b5b6200083e8262000a3a565b9050602081019050919050565b600082825260208201905092915050565b60006200086982620008ed565b91506200087683620008ed565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115620008ae57620008ad62000999565b5b828201905092915050565b6000620008c682620008cd565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b8381101562000917578082015181840152602081019050620008fa565b8381111562000927576000848401525b50505050565b600060028204905060018216806200094657607f821691505b602082108114156200095d576200095c620009c8565b5b50919050565b6200096e8262000a3a565b810181811067ffffffffffffffff8211171562000990576200098f620009f7565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b7f45524332305061757361626c653a20746f6b656e207472616e7366657220776860008201527f696c652070617573656400000000000000000000000000000000000000000000602082015250565b62000ace81620008b9565b811462000ada57600080fd5b50565b62000ae881620008ed565b811462000af457600080fd5b50565b6154778062000b076000396000f3fe608060405234801561001057600080fd5b50600436106102535760003560e01c80638456cb5911610146578063b5a5767c116100c3578063dd62ed3e11610087578063dd62ed3e146106ae578063f05e777d146106de578063f1af4829146106fc578063f2fde38b14610718578063fa01fc2114610734578063fd7dd0571461075257610253565b8063b5a5767c1461061e578063c5c58b891461063a578063ce97554414610656578063cfb5192814610660578063d51d81271461069057610253565b80639e24bc371161010a5780639e24bc3714610542578063a457c2d71461055e578063a9059cbb1461058e578063b273fc9a146105be578063b36cc8e7146105ee57610253565b80638456cb59146104c45780638b5f09c1146104ce5780638c5b133f146104ea5780638da5cb5b1461050657806395d89b411461052457610253565b806339509351116101d457806360f556991161019857806360f556991461043457806369fe0e2d1461045257806370a082311461046e578063715018a61461049e57806379cc6790146104a857610253565b806339509351146103a45780633f4ba83a146103d457806342966c68146103de5780634349138e146103fa5780635c975abb1461041657610253565b80631a147def1161021b5780631a147def146102fe57806323b872dd1461031c5780632652c4931461034c578063313ce5671461036a57806337e75f6d1461038857610253565b806306fdde031461025857806307cd206e14610276578063095ea7b3146102945780631168c24c146102c457806318160ddd146102e0575b600080fd5b61026061076e565b60405161026d9190614309565b60405180910390f35b61027e610800565b60405161028b919061460b565b60405180910390f35b6102ae60048036038101906102a99190613ae0565b610806565b6040516102bb91906142d3565b60405180910390f35b6102de60048036038101906102d99190613ced565b610843565b005b6102e86108c9565b6040516102f5919061460b565b60405180910390f35b6103066108d3565b604051610313919061460b565b60405180910390f35b61033660048036038101906103319190613a8d565b6108d9565b60405161034391906142d3565b60405180910390f35b6103546109d1565b604051610361919061460b565b60405180910390f35b6103726109d7565b60405161037f9190614656565b60405180910390f35b6103a2600480360381019061039d9190613b20565b6109dc565b005b6103be60048036038101906103b99190613ae0565b610baf565b6040516103cb91906142d3565b60405180910390f35b6103dc610c5b565b005b6103f860048036038101906103f39190613ced565b610ce1565b005b610414600480360381019061040f9190613c0f565b610cf5565b005b61041e611093565b60405161042b91906142d3565b60405180910390f35b61043c6110aa565b604051610449919061460b565b60405180910390f35b61046c60048036038101906104679190613ced565b6110b0565b005b61048860048036038101906104839190613a20565b611136565b604051610495919061460b565b60405180910390f35b6104a661117e565b005b6104c260048036038101906104bd9190613ae0565b611206565b005b6104cc611281565b005b6104e860048036038101906104e39190613ced565b611307565b005b61050460048036038101906104ff9190613ced565b61138d565b005b61050e611413565b60405161051b91906141db565b60405180910390f35b61052c61143d565b6040516105399190614309565b60405180910390f35b61055c60048036038101906105579190613ced565b6114cf565b005b61057860048036038101906105739190613ae0565b611555565b60405161058591906142d3565b60405180910390f35b6105a860048036038101906105a39190613ae0565b611640565b6040516105b591906142d3565b60405180910390f35b6105d860048036038101906105d39190613a20565b61167d565b6040516105e5919061460b565b60405180910390f35b61060860048036038101906106039190613a4d565b611695565b604051610615919061460b565b60405180910390f35b61063860048036038101906106339190613ced565b6116ba565b005b610654600480360381019061064f9190613ae0565b611740565b005b61065e61190b565b005b61067a60048036038101906106759190613ca4565b6119b3565b60405161068791906142ee565b60405180910390f35b6106986119dd565b6040516106a5919061460b565b60405180910390f35b6106c860048036038101906106c39190613a4d565b6119e3565b6040516106d5919061460b565b60405180910390f35b6106e6611a6a565b6040516106f391906142d3565b60405180910390f35b61071660048036038101906107119190613b73565b611a7d565b005b610732600480360381019061072d9190613a20565b611de4565b005b61073c611edc565b604051610749919061460b565b60405180910390f35b61076c60048036038101906107679190613ced565b611ee2565b005b60606003805461077d90614b6a565b80601f01602080910402602001604051908101604052809291908181526020018280546107a990614b6a565b80156107f65780601f106107cb576101008083540402835291602001916107f6565b820191906000526020600020905b8154815290600101906020018083116107d957829003601f168201915b5050505050905090565b60115481565b60006040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083a9061436b565b60405180910390fd5b61084b611fc5565b73ffffffffffffffffffffffffffffffffffffffff16610869611413565b73ffffffffffffffffffffffffffffffffffffffff16146108bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b6906144eb565b60405180910390fd5b8060118190555050565b6000600254905090565b600e5481565b60006108e6848484611fcd565b6000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610931611fc5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050828110156109b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a8906144cb565b60405180910390fd5b6109c5856109bd611fc5565b85840361224e565b60019150509392505050565b600f5481565b600090565b601960009054906101000a900460ff1615610a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a239061446b565b60405180910390fd5b610a34611fc5565b73ffffffffffffffffffffffffffffffffffffffff16610a52611413565b73ffffffffffffffffffffffffffffffffffffffff1614610aa8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9f906144eb565b60405180910390fd5b6000801b600c60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000848152602001908152602001600020541415610baa5780600c60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550610b6483600d54612419565b80828473ffffffffffffffffffffffffffffffffffffffff167fa47d864ce75457dd6fd6ea2212dfd39907f59d0a81f7c8abfe743e7f910cfa3260405160405180910390a45b505050565b6000610c51610bbc611fc5565b848460016000610bca611fc5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610c4c919061470a565b61224e565b6001905092915050565b610c63611fc5565b73ffffffffffffffffffffffffffffffffffffffff16610c81611413565b73ffffffffffffffffffffffffffffffffffffffff1614610cd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cce906144eb565b60405180910390fd5b610cdf612579565b565b610cf2610cec611fc5565b8261261b565b50565b84600b600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8e9061458b565b60405180910390fd5b600b600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055807f7cc135e0cebb02c3480ae5d74d377283180a2601f8f644edf7987b009316c63a60405160405180910390a26000601560008881526020019081526020016000206040518060800160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152602001600382018054610ee090614b6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610f0c90614b6a565b8015610f595780601f10610f2e57610100808354040283529160200191610f59565b820191906000526020600020905b815481529060010190602001808311610f3c57829003601f168201915b5050505050815250509050600073ffffffffffffffffffffffffffffffffffffffff16816020015173ffffffffffffffffffffffffffffffffffffffff161415610fd8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fcf9061440b565b60405180910390fd5b610fea8160000151826040015161261b565b61108a81600001518260200151836040015184606001518a8a80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050898980806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050506127f2565b50505050505050565b6000600560009054906101000a900460ff16905090565b60105481565b6110b8611fc5565b73ffffffffffffffffffffffffffffffffffffffff166110d6611413565b73ffffffffffffffffffffffffffffffffffffffff161461112c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611123906144eb565b60405180910390fd5b8060188190555050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611186611fc5565b73ffffffffffffffffffffffffffffffffffffffff166111a4611413565b73ffffffffffffffffffffffffffffffffffffffff16146111fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111f1906144eb565b60405180910390fd5b6112046000612aea565b565b600061121983611214611fc5565b6119e3565b90508181101561125e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112559061450b565b60405180910390fd5b6112728361126a611fc5565b84840361224e565b61127c838361261b565b505050565b611289611fc5565b73ffffffffffffffffffffffffffffffffffffffff166112a7611413565b73ffffffffffffffffffffffffffffffffffffffff16146112fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f4906144eb565b60405180910390fd5b611305612bb0565b565b61130f611fc5565b73ffffffffffffffffffffffffffffffffffffffff1661132d611413565b73ffffffffffffffffffffffffffffffffffffffff1614611383576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137a906144eb565b60405180910390fd5b80600f8190555050565b611395611fc5565b73ffffffffffffffffffffffffffffffffffffffff166113b3611413565b73ffffffffffffffffffffffffffffffffffffffff1614611409576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611400906144eb565b60405180910390fd5b8060108190555050565b6000600560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606004805461144c90614b6a565b80601f016020809104026020016040519081016040528092919081815260200182805461147890614b6a565b80156114c55780601f1061149a576101008083540402835291602001916114c5565b820191906000526020600020905b8154815290600101906020018083116114a857829003601f168201915b5050505050905090565b6114d7611fc5565b73ffffffffffffffffffffffffffffffffffffffff166114f5611413565b73ffffffffffffffffffffffffffffffffffffffff161461154b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611542906144eb565b60405180910390fd5b8060128190555050565b60008060016000611564611fc5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082811015611621576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611618906145ab565b60405180910390fd5b61163561162c611fc5565b8585840361224e565b600191505092915050565b60006040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116749061436b565b60405180910390fd5b60146020528060005260406000206000915090505481565b6013602052816000526040600020602052806000526040600020600091509150505481565b6116c2611fc5565b73ffffffffffffffffffffffffffffffffffffffff166116e0611413565b73ffffffffffffffffffffffffffffffffffffffff1614611736576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172d906144eb565b60405180910390fd5b80600d8190555050565b601960009054906101000a900460ff1615611790576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117879061446b565b60405180910390fd5b611798611fc5565b73ffffffffffffffffffffffffffffffffffffffff166117b6611413565b73ffffffffffffffffffffffffffffffffffffffff161461180c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611803906144eb565b60405180910390fd5b6000801b600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000205414611907576000801b600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020819055506000801b818373ffffffffffffffffffffffffffffffffffffffff167f633cace5793d041e54c2c70b3b27c6f59d15fd4ec6dd309f906a31369d42c34260405160405180910390a45b5050565b611913611fc5565b73ffffffffffffffffffffffffffffffffffffffff16611931611413565b73ffffffffffffffffffffffffffffffffffffffff1614611987576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197e906144eb565b60405180910390fd5b601960009054906101000a900460ff1615601960006101000a81548160ff021916908315150217905550565b6000808290506000815114156119cf576000801b9150506119d8565b60208301519150505b919050565b60125481565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b601960009054906101000a900460ff1681565b601960009054906101000a900460ff1615611acd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ac49061446b565b60405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b32906143ab565b60405180910390fd5b6000611b4633611136565b905082811015611b8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b829061448b565b60405180910390fd5b6000611ba160175430634349138e60e01b612c53565b9050611bf56040518060400160405280600d81526020017f7461726765744164647265737300000000000000000000000000000000000000815250611be587612c84565b83612e669092919063ffffffff16565b611c476040518060400160405280600d81526020017f736f757263654164647265737300000000000000000000000000000000000000815250611c3733612c84565b83612e669092919063ffffffff16565b611c916040518060400160405280600d81526020017f7472616e73616374696f6e4964000000000000000000000000000000000000008152508483612e669092919063ffffffff16565b6000611cc2601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683601854612e99565b905060405180608001604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff168152602001868152602001858152506015600083815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550604082015181600201556060820151816003019080519060200190611dd89291906137dc565b50905050505050505050565b611dec611fc5565b73ffffffffffffffffffffffffffffffffffffffff16611e0a611413565b73ffffffffffffffffffffffffffffffffffffffff1614611e60576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e57906144eb565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611ed0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ec7906143cb565b60405180910390fd5b611ed981612aea565b50565b600d5481565b611eea611fc5565b73ffffffffffffffffffffffffffffffffffffffff16611f08611413565b73ffffffffffffffffffffffffffffffffffffffff1614611f5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f55906144eb565b60405180910390fd5b80600e8190555050565b611f73838383611fc0565b611f7b611093565b15611fbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fb2906145eb565b60405180910390fd5b505050565b505050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561203d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120349061454b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156120ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a49061432b565b60405180910390fd5b6120b8838383612f63565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561213e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121359061444b565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546121d1919061470a565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612235919061460b565b60405180910390a3612248848484612f73565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156122be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b59061456b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561232e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612325906143eb565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258360405161240c919061460b565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612489576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612480906145cb565b60405180910390fd5b61249560008383612f63565b80600260008282546124a7919061470a565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546124fc919061470a565b925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612561919061460b565b60405180910390a361257560008383612f73565b5050565b612581611093565b6125c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b79061434b565b60405180910390fd5b6000600560006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612604611fc5565b60405161261191906141db565b60405180910390a1565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561268b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126829061452b565b60405180910390fd5b61269782600083612f63565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561271d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127149061438b565b60405180910390fd5b8181036000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816002600082825461277491906149ff565b92505081905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516127d9919061460b565b60405180910390a36127ed83600084612f73565b505050565b60005b82518160ff1610156128c157600061282e87858460ff168151811061281d5761281c614d2c565b5b602002602001015160105489612f78565b9050612857848360ff168151811061284957612848614d2c565b5b602002602001015182612419565b7fd10a84a6af20735b834fa7634e3c2f819fc7108ea4498c21dc1a853eeadb02da848360ff168151811061288e5761288d614d2c565b5b6020026020010151826040516128a59291906141f6565b60405180910390a15080806128b990614c16565b9150506127f5565b5060005b81518160ff1610156129915760006128fe87848460ff16815181106128ed576128ec614d2c565b5b602002602001015160115489612f78565b9050612927838360ff168151811061291957612918614d2c565b5b602002602001015182612419565b7f215c1a1edf8a8bef237b56242f6856daff6ec173a64970dd07fa5c8852aebe47838360ff168151811061295e5761295d614d2c565b5b6020026020010151826040516129759291906141f6565b60405180910390a150808061298990614c16565b9150506128c5565b5083601460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546129e1919061470a565b9250508190555083601360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612a74919061470a565b925050819055508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f28f6e4bebd410ff24835163f718e2ba8c267a2ba3b1bdc05c5bd100907356fa78686604051612ada929190614626565b60405180910390a3505050505050565b6000600560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612bb8611093565b15612bf8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bef906144ab565b60405180910390fd5b6001600560006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612c3c611fc5565b604051612c4991906141db565b60405180910390a1565b612c5b613862565b612c63613862565b612c7a858585846130b6909392919063ffffffff16565b9150509392505050565b60606000602867ffffffffffffffff811115612ca357612ca2614d5b565b5b6040519080825280601f01601f191660200182016040528015612cd55781602001600182028036833780820191505090505b50905060005b6014811015612e3d576000816013612cf391906149ff565b6008612cff919061496a565b6002612d0b919061484c565b8573ffffffffffffffffffffffffffffffffffffffff16612d2c9190614797565b60f81b9050600060108260f81c612d4391906147c8565b60f81b905060008160f81c6010612d5a91906149c4565b8360f81c612d689190614a33565b60f81b9050612d7682613166565b85856002612d84919061496a565b81518110612d9557612d94614d2c565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612dcd81613166565b856001866002612ddd919061496a565b612de7919061470a565b81518110612df857612df7614d2c565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505050508080612e3590614bcd565b915050612cdb565b5080604051602001612e4f91906141b9565b604051602081830303815290604052915050919050565b612e7d8284608001516131ac90919063ffffffff16565b612e948184608001516131ac90919063ffffffff16565b505050565b600080600a549050600181612eae919061470a565b600a819055506000633c6d41b960e01b600080876000015188604001518660028b6080015160000151604051602401612eed979695949392919061421f565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050612f58868386846131d1565b925050509392505050565b612f6e838383611f68565b505050565b505050565b600080601360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600081601460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461304791906149ff565b905080601254613057919061470a565b600f5485613065919061470a565b86613070919061496a565b61307a919061496a565b601254600e548661308b919061470a565b84613096919061496a565b6130a0919061496a565b6130aa9190614797565b92505050949350505050565b6130be613862565b6130ce8560800151610100613375565b508385600001818152505082856020019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508185604001907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050849050949350505050565b6000600a8260f81c60ff1610156131915760308260f81c6131879190614760565b60f81b90506131a7565b60578260f81c6131a19190614760565b60f81b90505b919050565b6131b982600383516133df565b6131cc818361356490919063ffffffff16565b505050565b600030846040516020016131e692919061418d565b60405160208183030381529060405280519060200120905084600b600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550807fb5e6e01e79f91267dc17b4e6314d5d4d03593d2ceee0fbb452b750bd70ea5af960405160405180910390a2600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634000aea08685856040518463ffffffff1660e01b81526004016132dc93929190614295565b602060405180830381600087803b1580156132f657600080fd5b505af115801561330a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061332e9190613be2565b61336d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133649061442b565b60405180910390fd5b949350505050565b61337d6138cf565b600060208361338c9190614c6e565b146133b85760208261339e9190614c6e565b60206133aa91906149ff565b826133b5919061470a565b91505b81836020018181525050604051808452600081528281016020016040525082905092915050565b60178167ffffffffffffffff1611613416576134108160058460ff16901b60ff16178461358690919063ffffffff16565b5061355f565b60ff8167ffffffffffffffff161161346c57613445601860058460ff16901b178461358690919063ffffffff16565b506134668167ffffffffffffffff166001856135a69092919063ffffffff16565b5061355e565b61ffff8167ffffffffffffffff16116134c35761349c601960058460ff16901b178461358690919063ffffffff16565b506134bd8167ffffffffffffffff166002856135a69092919063ffffffff16565b5061355d565b63ffffffff8167ffffffffffffffff161161351c576134f5601a60058460ff16901b178461358690919063ffffffff16565b506135168167ffffffffffffffff166004856135a69092919063ffffffff16565b5061355c565b613539601b60058460ff16901b178461358690919063ffffffff16565b5061355a8167ffffffffffffffff166008856135a69092919063ffffffff16565b505b5b5b5b505050565b61356c6138cf565b61357e838460000151518485516135c8565b905092915050565b61358e6138cf565b61359e83846000015151846136b7565b905092915050565b6135ae6138cf565b6135bf84856000015151858561370e565b90509392505050565b6135d06138cf565b82518211156135de57600080fd5b846020015182856135ef919061470a565b1115613624576136238560026136148860200151888761360f919061470a565b61379c565b61361e919061496a565b6137b8565b5b6000808651805187602083010193508088870111156136435787860182525b60208701925050505b6020841061368a5780518252602082613665919061470a565b9150602081613674919061470a565b905060208461368391906149ff565b935061364c565b60006001856020036101000a03905080198251168184511681811785525050508692505050949350505050565b6136bf6138cf565b836020015183106136e5576136e484600286602001516136df919061496a565b6137b8565b5b8351805160208583010184815381861415613701576001820183525b5050508390509392505050565b6137166138cf565b84602001518483613727919061470a565b111561374f5761374e856002868561373f919061470a565b613749919061496a565b6137b8565b5b6000600183610100613761919061484c565b61376b91906149ff565b9050855183868201018583198251161781528151858801111561378e5784870182525b505085915050949350505050565b6000818311156137ae578290506137b2565b8190505b92915050565b6000826000015190506137cb8383613375565b506137d68382613564565b50505050565b8280546137e890614b6a565b90600052602060002090601f01602090048101928261380a5760008555613851565b82601f1061382357805160ff1916838001178555613851565b82800160010185558215613851579182015b82811115613850578251825591602001919060010190613835565b5b50905061385e91906138e9565b5090565b6040518060a0016040528060008019168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001600081526020016138c96138cf565b81525090565b604051806040016040528060608152602001600081525090565b5b808211156139025760008160009055506001016138ea565b5090565b600061391961391484614696565b614671565b90508281526020810184848401111561393557613934614d99565b5b613940848285614b28565b509392505050565b600081359050613957816153e5565b92915050565b60008083601f84011261397357613972614d8f565b5b8235905067ffffffffffffffff8111156139905761398f614d8a565b5b6020830191508360208202830111156139ac576139ab614d94565b5b9250929050565b6000815190506139c2816153fc565b92915050565b6000813590506139d781615413565b92915050565b600082601f8301126139f2576139f1614d8f565b5b8135613a02848260208601613906565b91505092915050565b600081359050613a1a8161542a565b92915050565b600060208284031215613a3657613a35614da3565b5b6000613a4484828501613948565b91505092915050565b60008060408385031215613a6457613a63614da3565b5b6000613a7285828601613948565b9250506020613a8385828601613948565b9150509250929050565b600080600060608486031215613aa657613aa5614da3565b5b6000613ab486828701613948565b9350506020613ac586828701613948565b9250506040613ad686828701613a0b565b9150509250925092565b60008060408385031215613af757613af6614da3565b5b6000613b0585828601613948565b9250506020613b1685828601613a0b565b9150509250929050565b600080600060608486031215613b3957613b38614da3565b5b6000613b4786828701613948565b9350506020613b5886828701613a0b565b9250506040613b69868287016139c8565b9150509250925092565b600080600060608486031215613b8c57613b8b614da3565b5b6000613b9a86828701613948565b9350506020613bab86828701613a0b565b925050604084013567ffffffffffffffff811115613bcc57613bcb614d9e565b5b613bd8868287016139dd565b9150509250925092565b600060208284031215613bf857613bf7614da3565b5b6000613c06848285016139b3565b91505092915050565b600080600080600060608688031215613c2b57613c2a614da3565b5b6000613c39888289016139c8565b955050602086013567ffffffffffffffff811115613c5a57613c59614d9e565b5b613c668882890161395d565b9450945050604086013567ffffffffffffffff811115613c8957613c88614d9e565b5b613c958882890161395d565b92509250509295509295909350565b600060208284031215613cba57613cb9614da3565b5b600082013567ffffffffffffffff811115613cd857613cd7614d9e565b5b613ce4848285016139dd565b91505092915050565b600060208284031215613d0357613d02614da3565b5b6000613d1184828501613a0b565b91505092915050565b613d2381614a67565b82525050565b613d3281614a79565b82525050565b613d4181614a85565b82525050565b613d5081614a8f565b82525050565b6000613d61826146c7565b613d6b81856146dd565b9350613d7b818560208601614b37565b613d8481614da8565b840191505092915050565b613da0613d9b82614af2565b614c40565b82525050565b6000613db1826146d2565b613dbb81856146ee565b9350613dcb818560208601614b37565b613dd481614da8565b840191505092915050565b6000613dea826146d2565b613df481856146ff565b9350613e04818560208601614b37565b80840191505092915050565b6000613e1d6023836146ee565b9150613e2882614dd3565b604082019050919050565b6000613e406014836146ee565b9150613e4b82614e22565b602082019050919050565b6000613e63600c836146ee565b9150613e6e82614e4b565b602082019050919050565b6000613e866022836146ee565b9150613e9182614e74565b604082019050919050565b6000613ea96011836146ee565b9150613eb482614ec3565b602082019050919050565b6000613ecc6026836146ee565b9150613ed782614eec565b604082019050919050565b6000613eef6022836146ee565b9150613efa82614f3b565b604082019050919050565b6000613f126012836146ee565b9150613f1d82614f8a565b602082019050919050565b6000613f356002836146ff565b9150613f4082614fb3565b600282019050919050565b6000613f586023836146ee565b9150613f6382614fdc565b604082019050919050565b6000613f7b6026836146ee565b9150613f868261502b565b604082019050919050565b6000613f9e6015836146ee565b9150613fa98261507a565b602082019050919050565b6000613fc16023836146ee565b9150613fcc826150a3565b604082019050919050565b6000613fe46010836146ee565b9150613fef826150f2565b602082019050919050565b60006140076028836146ee565b91506140128261511b565b604082019050919050565b600061402a6020836146ee565b91506140358261516a565b602082019050919050565b600061404d6024836146ee565b915061405882615193565b604082019050919050565b60006140706021836146ee565b915061407b826151e2565b604082019050919050565b60006140936025836146ee565b915061409e82615231565b604082019050919050565b60006140b66024836146ee565b91506140c182615280565b604082019050919050565b60006140d96028836146ee565b91506140e4826152cf565b604082019050919050565b60006140fc6025836146ee565b91506141078261531e565b604082019050919050565b600061411f601f836146ee565b915061412a8261536d565b602082019050919050565b6000614142602a836146ee565b915061414d82615396565b604082019050919050565b61416181614adb565b82525050565b61417861417382614adb565b614c64565b82525050565b61418781614ae5565b82525050565b60006141998285613d8f565b6014820191506141a98284614167565b6020820191508190509392505050565b60006141c482613f28565b91506141d08284613ddf565b915081905092915050565b60006020820190506141f06000830184613d1a565b92915050565b600060408201905061420b6000830185613d1a565b6142186020830184614158565b9392505050565b600060e082019050614234600083018a613d1a565b6142416020830189614158565b61424e6040830188613d38565b61425b6060830187613d47565b6142686080830186614158565b61427560a0830185614158565b81810360c08301526142878184613d56565b905098975050505050505050565b60006060820190506142aa6000830186613d1a565b6142b76020830185614158565b81810360408301526142c98184613d56565b9050949350505050565b60006020820190506142e86000830184613d29565b92915050565b60006020820190506143036000830184613d38565b92915050565b600060208201905081810360008301526143238184613da6565b905092915050565b6000602082019050818103600083015261434481613e10565b9050919050565b6000602082019050818103600083015261436481613e33565b9050919050565b6000602082019050818103600083015261438481613e56565b9050919050565b600060208201905081810360008301526143a481613e79565b9050919050565b600060208201905081810360008301526143c481613e9c565b9050919050565b600060208201905081810360008301526143e481613ebf565b9050919050565b6000602082019050818103600083015261440481613ee2565b9050919050565b6000602082019050818103600083015261442481613f05565b9050919050565b6000602082019050818103600083015261444481613f4b565b9050919050565b6000602082019050818103600083015261446481613f6e565b9050919050565b6000602082019050818103600083015261448481613f91565b9050919050565b600060208201905081810360008301526144a481613fb4565b9050919050565b600060208201905081810360008301526144c481613fd7565b9050919050565b600060208201905081810360008301526144e481613ffa565b9050919050565b600060208201905081810360008301526145048161401d565b9050919050565b6000602082019050818103600083015261452481614040565b9050919050565b6000602082019050818103600083015261454481614063565b9050919050565b6000602082019050818103600083015261456481614086565b9050919050565b60006020820190508181036000830152614584816140a9565b9050919050565b600060208201905081810360008301526145a4816140cc565b9050919050565b600060208201905081810360008301526145c4816140ef565b9050919050565b600060208201905081810360008301526145e481614112565b9050919050565b6000602082019050818103600083015261460481614135565b9050919050565b60006020820190506146206000830184614158565b92915050565b600060408201905061463b6000830185614158565b818103602083015261464d8184613da6565b90509392505050565b600060208201905061466b600083018461417e565b92915050565b600061467b61468c565b90506146878282614b9c565b919050565b6000604051905090565b600067ffffffffffffffff8211156146b1576146b0614d5b565b5b6146ba82614da8565b9050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600061471582614adb565b915061472083614adb565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561475557614754614c9f565b5b828201905092915050565b600061476b82614ae5565b915061477683614ae5565b92508260ff0382111561478c5761478b614c9f565b5b828201905092915050565b60006147a282614adb565b91506147ad83614adb565b9250826147bd576147bc614cce565b5b828204905092915050565b60006147d382614ae5565b91506147de83614ae5565b9250826147ee576147ed614cce565b5b828204905092915050565b6000808291508390505b60018511156148435780860481111561481f5761481e614c9f565b5b600185161561482e5780820291505b808102905061483c85614dc6565b9450614803565b94509492505050565b600061485782614adb565b915061486283614adb565b925061488f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614897565b905092915050565b6000826148a75760019050614963565b816148b55760009050614963565b81600181146148cb57600281146148d557614904565b6001915050614963565b60ff8411156148e7576148e6614c9f565b5b8360020a9150848211156148fe576148fd614c9f565b5b50614963565b5060208310610133831016604e8410600b84101617156149395782820a90508381111561493457614933614c9f565b5b614963565b61494684848460016147f9565b9250905081840481111561495d5761495c614c9f565b5b81810290505b9392505050565b600061497582614adb565b915061498083614adb565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156149b9576149b8614c9f565b5b828202905092915050565b60006149cf82614ae5565b91506149da83614ae5565b92508160ff04831182151516156149f4576149f3614c9f565b5b828202905092915050565b6000614a0a82614adb565b9150614a1583614adb565b925082821015614a2857614a27614c9f565b5b828203905092915050565b6000614a3e82614ae5565b9150614a4983614ae5565b925082821015614a5c57614a5b614c9f565b5b828203905092915050565b6000614a7282614abb565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000614afd82614b04565b9050919050565b6000614b0f82614b16565b9050919050565b6000614b2182614abb565b9050919050565b82818337600083830152505050565b60005b83811015614b55578082015181840152602081019050614b3a565b83811115614b64576000848401525b50505050565b60006002820490506001821680614b8257607f821691505b60208210811415614b9657614b95614cfd565b5b50919050565b614ba582614da8565b810181811067ffffffffffffffff82111715614bc457614bc3614d5b565b5b80604052505050565b6000614bd882614adb565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614c0b57614c0a614c9f565b5b600182019050919050565b6000614c2182614ae5565b915060ff821415614c3557614c34614c9f565b5b600182019050919050565b6000614c4b82614c52565b9050919050565b6000614c5d82614db9565b9050919050565b6000819050919050565b6000614c7982614adb565b9150614c8483614adb565b925082614c9457614c93614cce565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b60008160011c9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b7f4e6f7420616c6c6f7765642e0000000000000000000000000000000000000000600082015250565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60008201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b7f73686f756c6420626520616e2075736572000000000000000000000000000000600082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b7f756e6b6e6f776e20656e646f72736d656e740000000000000000000000000000600082015250565b7f3078000000000000000000000000000000000000000000000000000000000000600082015250565b7f756e61626c6520746f207472616e73666572416e6443616c6c20746f206f726160008201527f636c650000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b7f436f6e7472616374206973206d6967726174696e670000000000000000000000600082015250565b7f5554543a20656e646f72736520616d6f756e7420657863656564732062616c6160008201527f6e63650000000000000000000000000000000000000000000000000000000000602082015250565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206160008201527f6c6c6f77616e6365000000000000000000000000000000000000000000000000602082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f45524332303a206275726e20616d6f756e74206578636565647320616c6c6f7760008201527f616e636500000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f536f75726365206d75737420626520746865206f7261636c65206f662074686560008201527f2072657175657374000000000000000000000000000000000000000000000000602082015250565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b7f45524332305061757361626c653a20746f6b656e207472616e7366657220776860008201527f696c652070617573656400000000000000000000000000000000000000000000602082015250565b6153ee81614a67565b81146153f957600080fd5b50565b61540581614a79565b811461541057600080fd5b50565b61541c81614a85565b811461542757600080fd5b50565b61543381614adb565b811461543e57600080fd5b5056fea2646970667358221220ba777900f57b1fd7aa880d7cb507e8421374c5f8eb565fa563962f7033b51a5464736f6c63430008070033000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073ac0b4ba4fc1c42b8dffa39f3e4e0e95eb9b8fd00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000005af3107a4000000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f100000000000000000000000000000000000000000000000000000000000000203065656337653164643064323437366361316138373264666236363333663438
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073ac0b4ba4fc1c42b8dffa39f3e4e0e95eb9b8fd00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000005af3107a4000000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f100000000000000000000000000000000000000000000000000000000000000203065656337653164643064323437366361316138373264666236363333663438
-----Decoded View---------------
Arg [0] : _mintAmount (uint256): 0
Arg [1] : _oracle (address): 0x73ac0b4ba4fc1c42b8dffa39f3e4e0e95eb9b8fd
Arg [2] : _jobId (string): 0eec7e1dd0d2476ca1a872dfb6633f48
Arg [3] : _fee (uint256): 100000000000000
Arg [4] : _link (address): 0xb0897686c545045afc77cf20ec7a532e3120e0f1
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : 00000000000000000000000073ac0b4ba4fc1c42b8dffa39f3e4e0e95eb9b8fd
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 00000000000000000000000000000000000000000000000000005af3107a4000
Arg [4] : 000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f1
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [6] : 3065656337653164643064323437366361316138373264666236363333663438