Source Code
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
YieldDistributor
Compiler Version
v0.8.26+commit.8a97fa7a
Contract Source Code (Solidity)
/**
*Submitted for verification at fraxscan.com on 2024-06-17
*/
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;
// lib/frax-standard-solidity/lib/forge-std/src/console2.sol
/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should
/// use `int256` and `uint256`. This modified version fixes that. This version is recommended
/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in
/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.
/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178
library console2 {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _castLogPayloadViewToPure(
function(bytes memory) internal view fnIn
) internal pure returns (function(bytes memory) internal pure fnOut) {
assembly {
fnOut := fnIn
}
}
function _sendLogPayload(bytes memory payload) internal pure {
_castLogPayloadViewToPure(_sendLogPayloadView)(payload);
}
function _sendLogPayloadView(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function log() internal pure {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function logUint(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function logString(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function log(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function log(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint256 p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
}
function log(uint256 p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
}
function log(uint256 p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
}
function log(uint256 p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
}
function log(string memory p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function log(string memory p0, int256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1));
}
function log(string memory p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
}
function log(bool p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
}
function log(address p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
}
function log(uint256 p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
}
function log(uint256 p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
}
function log(uint256 p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
}
function log(uint256 p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
}
function log(uint256 p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
}
function log(uint256 p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
}
function log(uint256 p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
}
function log(uint256 p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
}
function log(bool p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
}
function log(bool p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
}
function log(bool p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
}
function log(address p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
}
function log(address p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
}
function log(address p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}
// node_modules/@openzeppelin/contracts/security/ReentrancyGuard.sol
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
// node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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);
/**
* @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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from,
address to,
uint256 amount
) external returns (bool);
}
// node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
// node_modules/@openzeppelin/contracts/utils/Address.sol
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// node_modules/@openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
/**
* @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;
}
}
// src/contracts/VestedFXS-and-Flox/FPISLocker/IlFPISStructs.sol
// @version 0.2.8
/**
* ====================================================================
* | ______ _______ |
* | / _____________ __ __ / ____(_____ ____ _____ ________ |
* | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
* | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
* | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
* | |
* ====================================================================
* ======================== lFPISStructs ==============================
* ====================================================================
* Structs of lFPIS contracts (lFPIS)
* Frax Finance: https://github.com/FraxFinance
*/
interface IlFPISStructs {
/// @notice Detailed lock info for a user
/// @param user Address of the user
/// @param allLocks All of the locks of the user
/// @param numberOfLocks The total number of locks that the user has
/// @param activeLocks Only the active locks of the user
/// @param expiredLocks Only the expired locks of the user
/// @param totalFpis The total amount of FPIS that the user has for all, active, and expired locks respectively
struct DetailedUserLockInfo {
address user;
uint256 numberOfLocks;
LockedBalanceExtended[] allLocks;
LockedBalanceExtended[] activeLocks;
LockedBalanceExtended[] expiredLocks;
int128[3] totalFpis;
}
/// @notice Basic information about a lock
/// @param amount The amount that is locked
/// @param end The ending timestamp for the lock
/// @dev We cannot really do block numbers per se b/c slope is per time, not per block and per block could be fairly bad b/c Ethereum changes blocktimes. What we can do is to extrapolate ***At functions
struct LockedBalance {
int128 amount;
uint128 end; // This should more than suffice for our needs and allows the struct to be packed
}
/// @notice Extended information about a lock
/// @param id The ID of the lock
/// @param index The index of the lock. If index is 0, do not trust it unless isInUse is also true
/// @param amount The amount that is locked
/// @param end The ending timestamp for the lock
struct LockedBalanceExtended {
uint256 id;
uint128 index;
int128 amount;
uint128 end;
}
/// @notice Lock ID Info. Cannot be a simple mapping because lock indeces are in constant flux and index 0 vs null is ambiguous.
/// @param id The ID of the lock
/// @param index The index of the lock. If index is 0, do not trust it unless isInUse is also true
/// @param isInUse If the lock ID is currently in use
struct LockIdIdxInfo {
uint256 id;
uint128 index;
bool isInUse;
}
/// @notice Point in a user's lock
/// @param bias The bias of the point
/// @param slope The slope of the point
/// @param ts The timestamp of the point
/// @param blk The block of the point
/// @param fpisAmt The amount of FPIS at the point
struct Point {
int128 bias;
int128 slope; // - dweight / dt
uint256 ts;
uint256 blk; // block
uint256 fpisAmt;
}
/// @notice Longest lock info for a user
/// @param lock The longest lock of the user
/// @param lockIndex The index of the longest lock
/// @param user The address of the user
struct LongestLock {
LockedBalance lock;
uint128 lockIndex;
address user;
}
}
// src/contracts/VestedFXS-and-Flox/Flox/TransferHelper.sol
// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
error TransferHelperApproveFailed();
error TransferHelperTransferFailed();
error TransferHelperTransferFromFailed();
error TransferHelperTransferETHFailed();
function safeApprove(address token, address to, uint256 value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
// require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
if (!success || (data.length != 0 && !abi.decode(data, (bool)))) revert TransferHelperApproveFailed();
}
function safeTransfer(address token, address to, uint256 value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
// require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
if (!success || (data.length != 0 && !abi.decode(data, (bool)))) revert TransferHelperTransferFailed();
}
function safeTransferFrom(address token, address from, address to, uint256 value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
// require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
if (!success || (data.length != 0 && !abi.decode(data, (bool)))) revert TransferHelperTransferFromFailed();
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{ value: value }(new bytes(0));
// require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
if (!success) revert TransferHelperTransferETHFailed();
}
}
// src/contracts/VestedFXS-and-Flox/VestedFXS/IveFXSStructs.sol
// @version 0.2.8
/**
* ====================================================================
* | ______ _______ |
* | / _____________ __ __ / ____(_____ ____ _____ ________ |
* | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
* | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
* | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
* | |
* ====================================================================
* =============================== veFXS ==============================
* ====================================================================
* Structs VestedFXS (veFXS)
* Frax Finance: https://github.com/FraxFinance
*/
interface IveFXSStructs {
/// @notice Detailed lock info for a user
/// @param user Address of the user
/// @param allLocks All of the locks of the user
/// @param numberOfLocks The total number of locks that the user has
/// @param activeLocks Only the active locks of the user
/// @param expiredLocks Only the expired locks of the user
/// @param totalFxs The total amount of FXS that the user has for all, active, and expired locks respectively
struct DetailedUserLockInfo {
address user;
uint256 numberOfLocks;
LockedBalanceExtended[] allLocks;
LockedBalanceExtended[] activeLocks;
LockedBalanceExtended[] expiredLocks;
int128[3] totalFxs;
}
/// @notice Basic information about a lock
/// @param amount The amount that is locked
/// @param end The ending timestamp for the lock
/// @dev We cannot really do block numbers per se b/c slope is per time, not per block and per block could be fairly bad b/c Ethereum changes blocktimes. What we can do is to extrapolate ***At functions
struct LockedBalance {
int128 amount;
uint128 end; // This should more than suffice for our needs and allows the struct to be packed
}
/// @notice Extended information about a lock
/// @param id The ID of the lock
/// @param index The index of the lock. If index is 0, do not trust it unless isInUse is also true
/// @param amount The amount that is locked
/// @param end The ending timestamp for the lock
struct LockedBalanceExtended {
uint256 id;
uint128 index;
int128 amount;
uint128 end;
}
/// @notice Extended information about a lock
/// @param id The ID of the lock
/// @param index The index of the lock. If index is 0, do not trust it unless isInUse is also true
/// @param amount The amount that is locked
/// @param end The ending timestamp for the lock
/// @param location The address where the lock is being held
/// @param estimatedCurrLockVeFXS Estimated veFXS of this lock based on amount, end, and when this struct was generated
struct LockedBalanceExtendedV2 {
uint256 id;
uint128 index;
int128 amount;
uint128 end;
address location;
uint256 estimatedCurrLockVeFXS;
}
/// @notice Lock ID Info. Cannot be a simple mapping because lock indeces are in constant flux and index 0 vs null is ambiguous.
/// @param id The ID of the lock
/// @param index The index of the lock. If index is 0, do not trust it unless isInUse is also true
/// @param isInUse If the lock ID is currently in use
struct LockIdIdxInfo {
uint256 id;
uint128 index;
bool isInUse;
}
/// @notice Point in a user's lock
/// @param bias The bias of the point
/// @param slope The slope of the point
/// @param ts The timestamp of the point
/// @param blk The block of the point
/// @param fxsAmt The amount of FXS at the point
struct Point {
int128 bias;
int128 slope; // - dweight / dt
uint256 ts;
uint256 blk; // block
uint256 fxsAmt;
}
/// @notice Longest lock info for a user
/// @param lock The longest lock of the user
/// @param lockIndex The index of the longest lock
/// @param user The address of the user
struct LongestLock {
LockedBalance lock;
uint128 lockIndex;
address user;
}
}
// src/contracts/VestedFXS-and-Flox/VestedFXS/OwnedV2.sol
// https://docs.synthetix.io/contracts/Owned
contract OwnedV2 {
error OwnerCannotBeZero();
error InvalidOwnershipAcceptance();
error OnlyOwner();
address public owner;
address public nominatedOwner;
constructor(address _owner) {
// require(_owner != address(0), "Owner address cannot be 0");
if (_owner == address(0)) revert OwnerCannotBeZero();
owner = _owner;
emit OwnerChanged(address(0), _owner);
}
function nominateNewOwner(address _owner) external onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external {
// require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
if (msg.sender != nominatedOwner) revert InvalidOwnershipAcceptance();
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
modifier onlyOwner() {
// require(msg.sender == owner, "Only the contract owner may perform this action");
if (msg.sender != owner) revert OnlyOwner();
_;
}
function _onlyOwner() internal view {
if (msg.sender != owner) revert OnlyOwner();
}
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
}
// src/contracts/VestedFXS-and-Flox/VestedFXS/OwnedV2AutoMsgSender.sol
// https://docs.synthetix.io/contracts/Owned
contract OwnedV2AutoMsgSender {
error OwnerCannotBeZero();
error InvalidOwnershipAcceptance();
error OnlyOwner();
address public owner;
address public nominatedOwner;
constructor() {
owner = msg.sender;
emit OwnerChanged(address(0), msg.sender);
}
function nominateNewOwner(address _owner) external onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external {
// require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
if (msg.sender != nominatedOwner) revert InvalidOwnershipAcceptance();
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
modifier onlyOwner() {
// require(msg.sender == owner, "Only the contract owner may perform this action");
if (msg.sender != owner) revert OnlyOwner();
_;
}
function _onlyOwner() internal view {
if (msg.sender != owner) revert OnlyOwner();
}
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
}
// src/contracts/VestedFXS-and-Flox/interfaces/IL1VeFXS.sol
// @version 0.2.8
interface IL1VeFXS {
/// @dev amount and end of lock
struct LockedBalance {
uint128 amount;
uint64 end;
uint64 blockTimestamp;
}
function LOCKED_SLOT_INDEX() external view returns (uint256);
function acceptOwnership() external;
function adminProofVeFXS(address[] memory _addresses, LockedBalance[] memory _lockedBalances) external;
function balanceOf(address _address) external view returns (uint256 _balance);
function initialize(address _stateRootOracle, address _owner) external;
function locked(address account) external view returns (LockedBalance memory);
function owner() external view returns (address);
function pendingOwner() external view returns (address);
function proofVeFXS(
address _address,
uint256 _blockNumber,
bytes[] memory _accountProof,
bytes[] memory _storageProof1,
bytes[] memory _storageProof2
) external;
function renounceOwnership() external;
function transferOwnership(address newOwner) external;
function veFXSAddress() external view returns (address);
}
// node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.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);
}
// src/contracts/VestedFXS-and-Flox/VestedFXS/L1VeFXSTotalSupplyOracle.sol
/**
* ====================================================================
* | ______ _______ |
* | / _____________ __ __ / ____(_____ ____ _____ ________ |
* | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
* | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
* | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
* | |
* ====================================================================
* ===================== L1VeFXSTotalSupplyOracle =====================
* ====================================================================
* Bot-set Oracle for reporting the Ethereum Mainnet veFXS totalSupply() info.
* Eventually plan to update L1VeFXS with a proof-based solution
* Frax Finance: https://github.com/FraxFinance
*/
/* solhint-disable max-line-length, not-rely-on-time */
contract L1VeFXSTotalSupplyOracle is OwnedV2 {
/// @notice The last veFXS totalSupply data point
uint256 public totalSupplyStored;
/// @notice The block on Mainnet when the veFXS totalSupply was read
uint128 public blkWhenTotalSupplyRead;
/// @notice The timestamp on Mainnet when the veFXS totalSupply was read
uint128 public tsWhenTotalSupplyRead;
/// @notice When the information was last updated by the bot
uint256 public lastBotUpdate;
/// @notice Address of the bot that is allowed to update the contract
address public botAddress;
/**
* @notice Initialize contract
* @param _owner The owner of this contract
* @param _bot Address of the bot that is allowed to post
* @param _initTtlSupplyStored Initial/seed value of totalSupplyStored
* @param _initBlkWhenTotalSupplyRead Initial/seed value of blkWhenTotalSupplyRead
* @param _initTsWhenTtlSupplyRead Initial/seed value of tsWhenTotalSupplyRead
*/
constructor(
address _owner,
address _bot,
uint256 _initTtlSupplyStored,
uint128 _initBlkWhenTotalSupplyRead,
uint128 _initTsWhenTtlSupplyRead
) OwnedV2(_owner) {
// Set bot address
botAddress = _bot;
// Set seed values
totalSupplyStored = _initTtlSupplyStored;
blkWhenTotalSupplyRead = _initBlkWhenTotalSupplyRead;
tsWhenTotalSupplyRead = _initTsWhenTtlSupplyRead;
if (_initTsWhenTtlSupplyRead > 0) lastBotUpdate = _initTsWhenTtlSupplyRead;
}
/* ========== MODIFIERS ========== */
modifier onlyByOwnBot() {
require(msg.sender == owner || msg.sender == botAddress, "You are not the owner or the bot");
_;
}
/* ============ VIEWS ============ */
/// @notice Get the most recent totalSupply from Mainnet veFXS
/// @param _totalSupply The last reported Mainnet veFXS totalSupply
function totalSupply() external view returns (uint256 _totalSupply) {
return totalSupplyStored;
}
/// @notice Get the most recent totalSupply from Mainnet veFXS along with the time it was read
/// @param _totalSupply The last reported Mainnet veFXS totalSupply
/// @param _blk Block when the totalSupply was read on Mainnet
/// @param _ts Timestamp when the totalSupply was read on Mainnet
function totalSupplyExtra() external view returns (uint256 _totalSupply, uint128 _blk, uint128 _ts) {
return (totalSupplyStored, blkWhenTotalSupplyRead, tsWhenTotalSupplyRead);
}
// ==============================================================================
// BOT FUNCTIONS
// ==============================================================================
/// @notice Set the most recent totalSupply from Mainnet veFXS
/// @param _totalSupply The last reported Mainnet veFXS totalSupply
/// @param _blk Block when the totalSupply was read on Mainnet
/// @param _ts Timestamp when the totalSupply was read on Mainnet
function updateInfo(uint256 _totalSupply, uint128 _blk, uint128 _ts) external onlyByOwnBot {
totalSupplyStored = _totalSupply;
blkWhenTotalSupplyRead = _blk;
tsWhenTotalSupplyRead = _ts;
}
// ==============================================================================
// RESTRICTED FUNCTIONS
// ==============================================================================
/// @notice Set the bot address
/// @param _newBot The address of the bot
function setBot(address _newBot) external onlyOwner {
botAddress = _newBot;
}
// ==============================================================================
// EVENTS
// ==============================================================================
/// @notice When the veFXS info is updated
/// @param totalSupply veFXS totalSupply from mainnet
/// @param blk Block when the totalSupply was read on Mainnet
/// @param ts Timestamp when the totalSupply was read on Mainnet
event InfoUpdated(uint256 totalSupply, uint128 blk, uint128 ts);
}
// src/contracts/VestedFXS-and-Flox/interfaces/IFPISLocker.sol
// @version 0.2.8
/**
* ====================================================================
* | ______ _______ |
* | / _____________ __ __ / ____(_____ ____ _____ ________ |
* | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
* | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
* | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
* | |
* ====================================================================
* ============================ IFPISLocker ============================
* ====================================================================
* Frax Finance: https://github.com/FraxFinance
*/
interface IFPISLocker is IlFPISStructs {
function MAXTIME_INT128() external view returns (int128);
function MAXTIME_UINT256() external view returns (uint256);
function MAX_CONTRIBUTOR_LOCKS() external view returns (uint8);
function MAX_USER_LOCKS() external view returns (uint8);
function MULTIPLIER_UINT256() external view returns (uint256);
function VOTE_WEIGHT_MULTIPLIER_INT128() external view returns (int128);
function VOTE_WEIGHT_MULTIPLIER_UINT256() external view returns (uint256);
function VOTE_END_POWER_BASIS_POINTS_INT128() external view returns (int128);
function VOTE_END_POWER_BASIS_POINTS_UINT256() external view returns (uint256);
function MAX_BASIS_POINTS_INT128() external view returns (int128);
function MAX_BASIS_POINTS_UINT256() external view returns (uint256);
function FXS_CONVERSION_START_TIMESTAMP() external view returns (uint256);
function WEEK_UINT128() external view returns (uint128);
function WEEK_UINT256() external view returns (uint256);
function acceptTransferOwnership() external;
function admin() external view returns (address);
function balanceOf(address _addr) external view returns (uint256 _balance);
function balanceOfAllLocksAtBlock(address _addr, uint256 _block) external view returns (uint256 _balance);
function balanceOfAllLocksAtTime(address _addr, uint256 _timestamp) external view returns (uint256 _balance);
function balanceOfAt(address _addr, uint256 _block) external view returns (uint256 _balance);
function balanceOfOneLockAtBlock(
address _addr,
uint128 _lockIndex,
uint256 _block
) external view returns (uint256 _balance);
function balanceOfOneLockAtTime(
address _addr,
uint128 _lockIndex,
uint256 _timestamp
) external view returns (uint256 _balance);
function checkpoint() external;
function commitTransferOwnership(address _addr) external;
function createLock(address _addr, uint256 _value, uint128 _unlockTime) external returns (uint128);
function decimals() external view returns (uint256);
function depositFor(address _addr, uint256 _value, uint128 _lockIndex) external;
function emergencyUnlockActive() external view returns (bool);
function epoch() external view returns (uint256);
function findBlockEpoch(uint256 _block, uint256 _maxEpoch) external view returns (uint256);
function floxContributors(address) external view returns (bool);
function futureAdmin() external view returns (address);
function getLastUserSlope(address _addr, uint128 _lockIndex) external view returns (int128);
function increaseAmount(uint256 _value, uint128 _lockIndex) external;
function increaseUnlockTime(uint128 _unlockTime, uint128 _lockIndex) external;
function indicesToIds(address, uint128) external view returns (uint256);
function isPaused() external view returns (bool);
function locked(address, uint256) external view returns (int128 amount, uint128 end);
function lockedById(address _addr, uint256 _id) external view returns (LockedBalance memory _lockInfo);
function lockedByIndex(address _addr, uint128 _index) external view returns (LockedBalance memory _lockInfo);
function lockedEnd(address _addr, uint128 _index) external view returns (uint256);
function name() external view returns (string memory);
function nextId(address) external view returns (uint256);
function numLocks(address) external view returns (uint128);
function pointHistory(
uint256
) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fpisAmt);
function recoverIERC20(address _tokenAddr, uint256 _amount) external;
function setFloxContributor(address _floxContributor, bool _isFloxContributor) external;
function setLVPIDUtils(address _lFpisUtilsAddr) external;
function slopeChanges(uint256) external view returns (int128);
function supply() external view returns (uint256);
function supplyAt(Point memory _point, uint256 _t) external view returns (uint256);
function symbol() external view returns (string memory);
function toggleContractPause() external;
function activateEmergencyUnlock() external;
function fpis() external view returns (address);
function totalFPISSupply() external view returns (uint256);
function totalFPISSupplyAt(uint256 _block) external view returns (uint256);
function totalSupply() external view returns (uint256);
function totalSupply(uint256 _timestamp) external view returns (uint256);
function totalSupplyAt(uint256 _block) external view returns (uint256);
function userPointEpoch(address, uint256) external view returns (uint256);
function userPointHistory(
address,
uint256,
uint256
) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fpisAmt);
function userPointHistoryTs(address _addr, uint128 _lockIndex, uint256 _idx) external view returns (uint256);
function lFpisUtils() external view returns (address);
function version() external view returns (string memory);
function withdraw(uint128 _lockIndex) external;
}
// src/contracts/VestedFXS-and-Flox/interfaces/IVestedFXS.sol
// @version 0.2.8
/**
* ====================================================================
* | ______ _______ |
* | / _____________ __ __ / ____(_____ ____ _____ ________ |
* | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
* | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
* | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
* | |
* ====================================================================
* ============================ IVestedFXS ============================
* ====================================================================
* Frax Finance: https://github.com/FraxFinance
*/
interface IVestedFXS is IveFXSStructs {
function MAXTIME_INT128() external view returns (int128);
function MAXTIME_UINT256() external view returns (uint256);
function MAX_CONTRIBUTOR_LOCKS() external view returns (uint8);
function MAX_USER_LOCKS() external view returns (uint8);
function MULTIPLIER_UINT256() external view returns (uint256);
function VOTE_WEIGHT_MULTIPLIER_INT128() external view returns (int128);
function VOTE_WEIGHT_MULTIPLIER_UINT256() external view returns (uint256);
function WEEK_UINT128() external view returns (uint128);
function WEEK_UINT256() external view returns (uint256);
function acceptTransferOwnership() external;
function admin() external view returns (address);
function balanceOf(address _addr) external view returns (uint256 _balance);
function balanceOfAllLocksAtBlock(address _addr, uint256 _block) external view returns (uint256 _balance);
function balanceOfAllLocksAtTime(address _addr, uint256 _timestamp) external view returns (uint256 _balance);
function balanceOfAt(address _addr, uint256 _block) external view returns (uint256 _balance);
function balanceOfOneLockAtBlock(
address _addr,
uint128 _lockIndex,
uint256 _block
) external view returns (uint256 _balance);
function balanceOfOneLockAtTime(
address _addr,
uint128 _lockIndex,
uint256 _timestamp
) external view returns (uint256 _balance);
function checkpoint() external;
function commitTransferOwnership(address _addr) external;
function createLock(address _addr, uint256 _value, uint128 _unlockTime) external returns (uint128, uint256);
function decimals() external view returns (uint256);
function depositFor(address _addr, uint256 _value, uint128 _lockIndex) external;
function emergencyUnlockActive() external view returns (bool);
function epoch() external view returns (uint256);
function findBlockEpoch(uint256 _block, uint256 _maxEpoch) external view returns (uint256);
function floxContributors(address) external view returns (bool);
function futureAdmin() external view returns (address);
function getLastUserSlope(address _addr, uint128 _lockIndex) external view returns (int128);
function increaseAmount(uint256 _value, uint128 _lockIndex) external;
function increaseUnlockTime(uint128 _unlockTime, uint128 _lockIndex) external;
function indicesToIds(address, uint128) external view returns (uint256);
function isPaused() external view returns (bool);
function locked(address, uint256) external view returns (int128 amount, uint128 end);
function lockedById(address _addr, uint256 _id) external view returns (LockedBalance memory _lockInfo);
function lockedByIndex(address _addr, uint128 _index) external view returns (LockedBalance memory _lockInfo);
function lockedEnd(address _addr, uint128 _index) external view returns (uint256);
function name() external view returns (string memory);
function nextId(address) external view returns (uint256);
function numLocks(address) external view returns (uint128);
function pointHistory(
uint256
) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxsAmt);
function recoverIERC20(address _tokenAddr, uint256 _amount) external;
function setFloxContributor(address _floxContributor, bool _isFloxContributor) external;
function setVeFXSUtils(address _veFxsUtilsAddr) external;
function slopeChanges(uint256) external view returns (int128);
function supply() external view returns (uint256);
function supplyAt(Point memory _point, uint256 _t) external view returns (uint256);
function symbol() external view returns (string memory);
function toggleContractPause() external;
function activateEmergencyUnlock() external;
function token() external view returns (address);
function totalFXSSupply() external view returns (uint256);
function totalFXSSupplyAt(uint256 _block) external view returns (uint256);
function totalSupply() external view returns (uint256);
function totalSupply(uint256 _timestamp) external view returns (uint256);
function totalSupplyAt(uint256 _block) external view returns (uint256);
function userPointEpoch(address, uint256) external view returns (uint256);
function userPointHistory(
address,
uint256,
uint256
) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxsAmt);
function userPointHistoryTs(address _addr, uint128 _lockIndex, uint256 _idx) external view returns (uint256);
function veFxsUtils() external view returns (address);
function version() external view returns (string memory);
function withdraw(uint128 _lockIndex) external;
function numberOfFloxContributorCreatedLocks(address _user) external view returns (uint256);
}
// src/contracts/VestedFXS-and-Flox/interfaces/IVestedFXSUtils.sol
// @version 0.2.8
/**
* ====================================================================
* | ______ _______ |
* | / _____________ __ __ / ____(_____ ____ _____ ________ |
* | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
* | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
* | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
* | |
* ====================================================================
* ========================= IVestedFXSUtils ==========================
* ====================================================================
* Interface for helper and utility functions for VestedFXS
* Frax Finance: https://github.com/FraxFinance
*/
interface IVestedFXSUtils is IveFXSStructs {
function getDetailedUserLockInfo(address user) external view returns (DetailedUserLockInfo memory);
function getDetailedUserLockInfoBulk(address[] memory users) external view returns (DetailedUserLockInfo[] memory);
function getLongestLock(address user) external view returns (LockedBalance memory, uint128);
function getLongestLockBulk(address[] memory users) external view returns (LongestLock[] memory);
function getCrudeExpectedVeFXSOneLock(int128 _fxsAmount, uint128 _lockSecsU128) external view returns (uint256);
function getCrudeExpectedVeFXSMultiLock(
int128[] memory _fxsAmounts,
uint128[] memory _lockSecsU128
) external view returns (uint256);
function getCrudeExpectedVeFXSUser(address _user) external view returns (uint256);
}
// node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.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:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, 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}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, 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}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, 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) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, 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) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* 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:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, 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 Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - 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 {}
}
// node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
// src/contracts/VestedFXS-and-Flox/FPISLocker/FPISLockerUtils.sol
// @version 0.2.8
/**
* ====================================================================
* | ______ _______ |
* | / _____________ __ __ / ____(_____ ____ _____ ________ |
* | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
* | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
* | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
* | |
* ====================================================================
* ========================= FPISLockerUtils ==========================
* ====================================================================
* Helper and utility functions for VestedFXS
* Frax Finance: https://github.com/FraxFinance
*/
/**
*
* Voting escrow to have time-weighted votes
* Votes have a weight depending on time, so that users are committed
* to the future of (whatever they are voting for).
* The weight in this implementation is linear, and lock cannot be more than maxtime:
* w ^
* 1 + /
* | /
* | /
* | /
* |/
* 0 +--------+------> time
* maxtime (4 years?)
*/
/**
* @title FPISLockerUtils
* @author Frax Finance
* @notice This utility smart contract provides functions to get extended information from the FPISLocker contract.
*/
contract FPISLockerUtils is IlFPISStructs {
IFPISLocker public immutable lFPIS;
IERC20Metadata public immutable fpis;
uint256 public constant VOTE_END_POWER_BASIS_POINTS_UINT256 = 3330;
uint256 public constant MAX_BASIS_POINTS_UINT256 = 10_000;
/**
* @notice Contract constructor
* @param _FPISLocker Address of the FPISLocker contract
*/
constructor(address _FPISLocker) {
lFPIS = IFPISLocker(_FPISLocker);
fpis = IERC20Metadata(lFPIS.fpis());
}
/**
* @notice Used to get all of the locks of a given user.
* @dev The locks are retrieved indiscriminately, regardless of whether they are active or expired.
* @param _user Address of the user
* @return _userLockInfo DetailedUserLockInfo for the user. Includes _allLocks, _activeLocks, _expiredLocks, and FXS totals for these respectively
* @dev This lives on Fraxtal and will mostly be read-called in UIs, so gas not really an issue here
*/
function getDetailedUserLockInfo(address _user) public view returns (DetailedUserLockInfo memory _userLockInfo) {
// Get the total number of locks
uint256 _totalLocks = lFPIS.numLocks(_user);
uint128 _numberOfActiveLocks;
// Set the number locks for the user
_userLockInfo.numberOfLocks = _totalLocks;
// Set the user
_userLockInfo.user = _user;
// Initialize _allLocks
_userLockInfo.allLocks = new LockedBalanceExtended[](_totalLocks);
// Initial _isActive, which tracks if a given index is active
bool[] memory _isActive = new bool[](_totalLocks);
// Loop through all of the locks
for (uint256 i; i < _userLockInfo.allLocks.length; ) {
// Update the _allLocks return data
LockedBalance memory _thisLock = lFPIS.lockedByIndex(_user, uint128(i));
_userLockInfo.allLocks[i].id = lFPIS.indicesToIds(_user, uint128(i));
_userLockInfo.allLocks[i].index = uint128(i);
_userLockInfo.allLocks[i].amount = _thisLock.amount;
_userLockInfo.allLocks[i].end = _thisLock.end;
_userLockInfo.totalFpis[0] += _thisLock.amount;
// Determine whether it is active or expired
if (_thisLock.end > block.timestamp) {
// Update isActive tracking
_isActive[i] = true;
// Update _totalFxs for active locks
_userLockInfo.totalFpis[1] += _thisLock.amount;
unchecked {
++_numberOfActiveLocks;
}
} else {
// Update _totalFxs for expired locks
_userLockInfo.totalFpis[2] += _thisLock.amount;
}
unchecked {
++i;
}
}
// Initialize _activeLocks and _expiredLocks
_userLockInfo.activeLocks = new LockedBalanceExtended[](_numberOfActiveLocks);
_userLockInfo.expiredLocks = new LockedBalanceExtended[](_totalLocks - _numberOfActiveLocks);
// Loop through all of the locks again, this time for assigning to _activeLocks and _expiredLocks
uint128 _activeCounter;
uint128 _expiredCounter;
for (uint256 i; i < _userLockInfo.allLocks.length; ) {
// Get the lock info
LockedBalanceExtended memory _thisLock = _userLockInfo.allLocks[i];
// Sort the lock as either active or expired
if (_isActive[i]) {
// Active
_userLockInfo.activeLocks[_activeCounter] = _thisLock;
unchecked {
++_activeCounter;
}
} else {
// Expired
_userLockInfo.expiredLocks[_expiredCounter] = _thisLock;
unchecked {
++_expiredCounter;
}
}
unchecked {
++i;
}
}
}
/**
* @notice Used to get all of the locks of the given users. Same underlying code as getDetailedUserLockInfo
* @dev The locks are retrieved indiscriminately, regardless of whether they are active or expired.
* @param _users Addresses of the users
* @return _userLockInfos DetailedUserLockInfo[] for the users. Includes _allLocks, _activeLocks, _expiredLocks, and FXS totals for these respectively
* @dev This lives on Fraxtal and will mostly be read-called in UIs, so gas not really an issue here
*/
function getDetailedUserLockInfoBulk(
address[] memory _users
) public view returns (DetailedUserLockInfo[] memory _userLockInfos) {
// Save the number of user addresses
uint256 _numUsers = _users.length;
// Initialize the return array
_userLockInfos = new DetailedUserLockInfo[](_numUsers);
// Loop through all of the users and get their detailed lock info
for (uint256 i = 0; i < _numUsers; ) {
_userLockInfos[i] = getDetailedUserLockInfo(_users[i]);
unchecked {
i++;
}
}
}
/**
* @notice Used to get the longest lock of a given user.
* @dev The longest lock is the lock with the timestamp furthest in the future (can also be in the past if there are no active locks).
* @param user Address of the user
* @return The longest lock of the user
* @return The index of the longest lock
*/
function getLongestLock(address user) public view returns (LockedBalance memory, uint128) {
LockedBalance[] memory locks = new LockedBalance[](lFPIS.numLocks(user));
LockedBalance memory longestLock;
uint128 longestLockIndex;
for (uint256 i = 0; i < locks.length; ) {
uint128 currentEnd = lFPIS.lockedByIndex(user, uint128(i)).end;
if (currentEnd > longestLock.end) {
longestLock.end = currentEnd;
longestLock.amount = lFPIS.lockedByIndex(user, uint128(i)).amount;
longestLockIndex = uint128(i);
}
unchecked {
i++;
}
}
return (longestLock, longestLockIndex);
}
/**
* @notice Used to get longest locks of muliple users.
* @dev This returns the longest lock indiscriminately, regardless of whether it is active or expired.
* @dev The return value is an array of LongestLock structs, which contain the lock, the index of the lock, and the user.
* @param users Array of addresses of the users
* @return The LongestLocks of the users
*/
function getLongestLockBulk(address[] memory users) public view returns (LongestLock[] memory) {
LongestLock[] memory longestLocks = new LongestLock[](users.length);
LockedBalance memory longestLock;
uint128 longestLockIndex;
for (uint256 i = 0; i < users.length; ) {
for (uint256 j; j < lFPIS.numLocks(users[i]); ) {
uint128 currentEnd = lFPIS.lockedByIndex(users[i], uint128(j)).end;
if (currentEnd > longestLock.end) {
longestLock.end = currentEnd;
longestLock.amount = lFPIS.lockedByIndex(users[i], uint128(j)).amount;
longestLockIndex = uint128(j);
}
unchecked {
++j;
}
}
longestLocks[i] = LongestLock({ lock: longestLock, lockIndex: longestLockIndex, user: users[i] });
delete longestLock;
delete longestLockIndex;
unchecked {
++i;
}
}
return longestLocks;
}
/**
* @notice Calculate the APPROXIMATE amount of lFPIS, given an FPIS amount and a lock length. Cruder version of balanceOf math. Useful for sanity checks.
* @param _fpisAmount The amount of FPIS
* @param _lockSecsU128 The length of the lock
* @return _expectedLFPIS The expected amount of lFPIS. May be slightly off from actual (~1%)
* @dev Useful to compare to the slope/bias-based balancedOf to make sure the math is working
*/
function getCrudeExpectedLFPISOneLock(
int128 _fpisAmount,
uint128 _lockSecsU128
) public view returns (uint256 _expectedLFPIS) {
// lFPIS = FPIS in emergency unlock situation
if (lFPIS.emergencyUnlockActive()) {
return (uint256(int256(_fpisAmount)) * VOTE_END_POWER_BASIS_POINTS_UINT256) / MAX_BASIS_POINTS_UINT256;
}
// Truncate _timeLeft down to the nearest week
int128 _lockSecsI128 = int128((_lockSecsU128 / lFPIS.WEEK_UINT128()) * lFPIS.WEEK_UINT128());
// Calculate the expected lFPIS
_expectedLFPIS = uint256(
uint128(
((_fpisAmount * lFPIS.VOTE_END_POWER_BASIS_POINTS_INT128()) / lFPIS.MAX_BASIS_POINTS_INT128()) +
((_fpisAmount * _lockSecsI128 * lFPIS.VOTE_WEIGHT_MULTIPLIER_INT128()) /
lFPIS.MAXTIME_INT128() /
lFPIS.MAX_BASIS_POINTS_INT128())
)
);
}
/**
* @notice Calculate the APPROXIMATE amount of lFPIS, given FPIS amounts and lock lengths. Cruder version of balanceOf math. Useful for sanity checks.
* @param _fpisAmounts The amounts of FPIS
* @param _lockSecsU128 The length of the locks
* @return _expectedLFPIS The expected amount of lFPIS (summed). May be slightly off from actual (~1%)
* @dev Useful to compare to the slope/bias-based balancedOf to make sure the math is working
*/
function getCrudeExpectedLFPISMultiLock(
int128[] memory _fpisAmounts,
uint128[] memory _lockSecsU128
) public view returns (uint256 _expectedLFPIS) {
// See if you are in an emergency unlock situation
bool _isEmergencyUnlockActive = lFPIS.emergencyUnlockActive();
// Loop through the locks
for (uint128 i = 0; i < _fpisAmounts.length; ++i) {
// lFPIS = FPIS in emergency unlock situation
if (_isEmergencyUnlockActive) {
_expectedLFPIS +=
(uint256(int256(_fpisAmounts[i])) * VOTE_END_POWER_BASIS_POINTS_UINT256) /
MAX_BASIS_POINTS_UINT256;
} else {
_expectedLFPIS += getCrudeExpectedLFPISOneLock(_fpisAmounts[i], _lockSecsU128[i]);
}
}
}
/**
* @notice Calculate the APPROXIMATE amount of lFPIS a specific user should have. Cruder version of balanceOf math. Useful for sanity checks.
* @param _user The address of the user
* @return _expectedLFPIS The expected amount of lFPIS (summed). May be slightly off from actual (~1%)
* @dev Useful to compare to the slope/bias-based balancedOf to make sure the math is working
*/
function getCrudeExpectedLFPISUser(address _user) public view returns (uint256 _expectedLFPIS) {
// Get all of the user's locks
DetailedUserLockInfo memory _userLockInfo = getDetailedUserLockInfo(_user);
// See if you are in an emergency unlock situation
bool _isEmergencyUnlockActive = lFPIS.emergencyUnlockActive();
// Loop through all of the user's locks
for (uint128 i = 0; i < _userLockInfo.numberOfLocks; ) {
// Get the lock info
LockedBalanceExtended memory _lockInfo = _userLockInfo.allLocks[i];
// For the emergency unlock situation, lFPIS = FPIS
if (_isEmergencyUnlockActive) {
_expectedLFPIS +=
(uint256(int256(_lockInfo.amount)) * VOTE_END_POWER_BASIS_POINTS_UINT256) /
MAX_BASIS_POINTS_UINT256;
} else {
// Get the lock time to use
uint128 _lockSecsToUse;
if (_lockInfo.end < uint128(block.timestamp)) {
_lockSecsToUse = 0;
} else {
_lockSecsToUse = _lockInfo.end - uint128(block.timestamp);
}
// Get the approximate lFPIS
_expectedLFPIS += getCrudeExpectedLFPISOneLock(_lockInfo.amount, _lockSecsToUse);
}
unchecked {
++i;
}
}
}
}
// src/contracts/VestedFXS-and-Flox/VestedFXS/VeFXSAggregator.sol
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ========================= VeFXSAggregator ==========================
// ====================================================================
// Looks at various sources of veFXS for a given address. Also gives totalSupply
// Includes:
// 1) L1veFXS: Lives on Fraxtal. Users can prove their Ethereum Mainnet vefxs.vy balance and end time so it is visible on Fraxtal
// 2) VestedFXS: Fraxtal-native veFXS. Basically the same as Mainnet vefxs.vy but lives on Fraxtal
// 3) FPISLocker: Locked FPIS on Fraxtal that eventually will be converted to FXS per https://snapshot.org/#/frax.eth/proposal/0x9ec68015d6f6fd185f600a255e494f4ff926bbdd9b268f4bd712983a6e68fb5a
// 4+) Future capability to add even more sources of veFXS
// Frax Finance: https://github.com/FraxFinance
// Primary Author(s)
// Travis Moore: https://github.com/FortisFortuna
// Reviewer(s) / Contributor(s)
// Jan Turk: https://github.com/ThunderDeliverer
// Dennis: https://github.com/denett
// Sam Kazemian: https://github.com/samkazemian
// Originally inspired by Synthetix.io, but heavily modified by the Frax team (veFXS portion)
// https://github.com/Synthetixio/synthetix/blob/develop/contracts/StakingRewards.sol
// import "forge-std/console2.sol";
contract VeFXSAggregator is OwnedV2AutoMsgSender, IveFXSStructs {
using SafeERC20 for ERC20;
// ==============================================================================
// STATE VARIABLES
// ==============================================================================
// Instances
// -------------------------
/// @notice The Fraxtal veFXS contract
IVestedFXS public veFXS;
/// @notice The FPIS Locker contract
IFPISLocker public fpisLocker;
/// @notice The IL1VeFXS contract (snapshot of Ethereum Mainnet veFXS.vy)
IL1VeFXS public l1veFXS;
/// @notice The Fraxtal veFXS veFXSUtils contract
IVestedFXSUtils public veFXSUtils;
/// @notice The Fraxtal FPIS Locker FPISLockerUtils contract
FPISLockerUtils public lFpisUtils;
/// @notice Oracle on Fraxtal that reports Mainnet veFXS totalSupply.
L1VeFXSTotalSupplyOracle public l1VeFXSTotalSupplyOracle;
// Addresses
// -------------------------
/// @notice Address of the timelock
address public timelockAddress;
/// @notice Array of additional / future veFXS-like contracts
address[] public addlVeContractsArr;
/// @notice Whether an address is an additional / future veFXS-like contract
mapping(address => bool) public addlVeContracts;
// Misc
// -------------------------
/// @notice If the contract was initialized
bool wasInitialized;
// /// @dev reserve extra storage for future upgrades
// uint256[50] private __gap;
// ==============================================================================
// STRUCTS
// ==============================================================================
/// @notice A more detailed breakdown of the veFXS supply
/// @param vestedFXSTotal Fraxtal-native VestedFXS totalSupply
/// @param fpisLockerTotal FPISLocker's totalSupply
/// @param l1veFXSTotal Sum of L1veFXS as reported by the L1VeFXSTotalSupplyOracle
/// @param otherSourcesTotal Sum of the totalSupply's of other veFXS sources
/// @param grandTotal Grand totalSupply of all veFXS sources
struct DetailedTotalSupplyInfo {
uint256 vestedFXSTotal;
uint256 fpisLockerTotal;
uint256 l1veFXSTotal;
uint256 otherSourcesTotal;
uint256 grandTotal;
}
// ==============================================================================
// MODIFIERS
// ==============================================================================
/// @notice A modifier that only allows the contract owner or the timelock to call
modifier onlyByOwnGov() {
if (msg.sender != owner && msg.sender != timelockAddress) revert NotOwnerOrTimelock();
_;
}
// ==============================================================================
// CONSTRUCTOR
// ==============================================================================
constructor() {
// Set the contract as initialized
wasInitialized = true;
}
/**
* @notice Initialize contract
* @param _owner The owner of this contract
* @param _timelockAddress Address of the timelock
* @param _veAddresses The addresses: 0: veFXS, 1: veFXSUtils, 2: FPIS Locker, 3: FPISLockerUtils, 4: L1VeFXS, 5: L1VeFXSTotalSupplyOracle
*/
function initialize(address _owner, address _timelockAddress, address[6] memory _veAddresses) public {
// Safety checks - no validation on admin in case this is initialized without admin
if (wasInitialized) revert InitializeFailed();
// Set owner for OwnedV2
owner = _owner;
// Set misc addresses
timelockAddress = _timelockAddress;
// Set the Fraxtal VestedFXS
veFXS = IVestedFXS(_veAddresses[0]);
veFXSUtils = IVestedFXSUtils(_veAddresses[1]);
// (Optional) Set the FPISLocker
if ((_veAddresses[2] != address(0)) && (_veAddresses[3] != address(0))) {
fpisLocker = IFPISLocker(_veAddresses[2]);
lFpisUtils = FPISLockerUtils(_veAddresses[3]);
}
// (Optional) Set the L1VeFXS andL1VeFXSTotalSupplyOracle
if ((_veAddresses[4] != address(0)) && (_veAddresses[5] != address(0))) {
l1veFXS = IL1VeFXS(_veAddresses[4]);
l1VeFXSTotalSupplyOracle = L1VeFXSTotalSupplyOracle(_veAddresses[5]);
}
// Set the contract as initialized
wasInitialized = true;
}
// ==============================================================================
// VIEWS
// ==============================================================================
/// @notice Total veFXS of a user from multiple different sources, such as the FPIS Locker, L1VeFXS, and Fraxtal veFXS
/// @param _user The user to check
/// @return _currBal The veFXS balance
function ttlCombinedVeFXS(address _user) public view returns (uint256 _currBal) {
// Look at the OG 3 sources first
// ===========================
// VestedFXS on Fraxtal
_currBal = veFXS.balanceOf(_user);
// (Optional) FPIS Locker on Fraxtal
if (address(fpisLocker) != address(0)) _currBal += fpisLocker.balanceOf(_user);
// (Optional) L1VeFXS: snapshot of Ethereum Mainnet veFXS. Lives on Fraxtal
if ((address(l1veFXS) != address(0)) && (address(l1VeFXSTotalSupplyOracle) != address(0))) {
_currBal += l1veFXS.balanceOf(_user);
}
// (Optional) Look at any extra veFXS sources
for (uint256 i; i < addlVeContractsArr.length; ) {
address _veAddr = addlVeContractsArr[i];
if (_veAddr != address(0)) {
_currBal += IVestedFXS(_veAddr).balanceOf(_user);
}
unchecked {
++i;
}
}
}
/// @notice Detailed veFXS totalSupply from multiple different sources, such as the FPIS Locker, L1VeFXS, and Fraxtal veFXS. Non-checkpointed L1VeFXS is excluded
/// @return _supplyInfo Detailed breakdown of veFXS from different sources
function ttlCombinedVeFXSTotalSupplyDetailed() public view returns (DetailedTotalSupplyInfo memory _supplyInfo) {
// Look at the OG 3 sources first
// ===========================
// VestedFXS on Fraxtal
_supplyInfo.vestedFXSTotal = veFXS.totalSupply();
_supplyInfo.grandTotal = _supplyInfo.vestedFXSTotal;
// console2.log("{agg} veFXS.totalSupply(): %s", _supplyInfo.vestedFXSTotal);
// (Optional) FPIS Locker on Fraxtal
if (address(fpisLocker) != address(0)) {
_supplyInfo.fpisLockerTotal = fpisLocker.totalSupply();
_supplyInfo.grandTotal += _supplyInfo.fpisLockerTotal;
// console2.log("{agg} fpisLocker.totalSupply(): %s", _supplyInfo.fpisLockerTotal);
}
// (Optional) L1VeFXS: snapshot of Ethereum Mainnet veFXS. Lives on Fraxtal
if ((address(l1veFXS) != address(0)) && (address(l1VeFXSTotalSupplyOracle) != address(0))) {
_supplyInfo.l1veFXSTotal = l1VeFXSTotalSupplyOracle.totalSupply();
_supplyInfo.grandTotal += _supplyInfo.l1veFXSTotal;
// console2.log("{agg} l1VeFXSTotalSupplyOracle.totalSupply(): %s", _supplyInfo.l1veFXSTotal);
}
// (Optional) Look at any extra veFXS sources
for (uint256 i; i < addlVeContractsArr.length; ) {
address _veAddr = addlVeContractsArr[i];
if (_veAddr != address(0)) {
uint256 _thisSupply = IVestedFXS(_veAddr).totalSupply();
_supplyInfo.otherSourcesTotal += _thisSupply;
_supplyInfo.grandTotal += _thisSupply;
// console2.log("{agg} addlVeContractsArr[%s].totalSupply(): %s", i, _thisSupply);
}
unchecked {
++i;
}
}
}
/// @notice Total veFXS totalSupply from multiple different sources, such as the FPIS Locker, L1VeFXS, and Fraxtal veFXS. Non-checkpointed L1VeFXS is excluded
/// @return _totalSupply The veFXS totalSupply from all sources
/// @dev Summarized version of ttlCombinedVeFXSTotalSupplyDetailed
function ttlCombinedVeFXSTotalSupply() public view returns (uint256 _totalSupply) {
DetailedTotalSupplyInfo memory _supplyInfo = ttlCombinedVeFXSTotalSupplyDetailed();
_totalSupply = _supplyInfo.grandTotal;
}
/// @notice Array of all extra veFXS-like contracts
/// @return _addresses The addresses
function allAddlVeContractsAddresses() external view returns (address[] memory _addresses) {
return addlVeContractsArr;
}
/// @notice Length of the array of all extra veFXS-like contracts
/// @return _length The length
function allAddlVeContractsLength() external view returns (uint256 _length) {
return addlVeContractsArr.length;
}
/// @notice Get all the active locks for a user
/// @param _account The account to get the locks for
/// @param _estimateCrudeVeFXS False to save gas. True to add the lock's estimated veFXS
/// @return _currActiveLocks Array of LockedBalanceExtendedV2 structs (all active locks)
function getAllCurrActiveLocks(
address _account,
bool _estimateCrudeVeFXS
) public view returns (LockedBalanceExtendedV2[] memory _currActiveLocks) {
// Prepare to allocate the return array. Not all of the locks will be active.
// OG 3 veFXS contracts
// ===================================
// Fraxtal VestedFXS
uint256 _maxArrSize = veFXS.numLocks(_account);
// (Optional) FPIS Locker
if (address(fpisLocker) != address(0)) _maxArrSize += fpisLocker.numLocks(_account);
// (Optional) L1VeFXS
if ((address(l1veFXS) != address(0)) && (address(l1VeFXSTotalSupplyOracle) != address(0))) {
_maxArrSize += 1; // Legacy veFXS on Mainnet only has one lock
}
// (Optional) Get the total number of locks in the additional veFXS contracts
for (uint256 i = 0; i < addlVeContractsArr.length; ) {
address _veAddr = addlVeContractsArr[i];
if (_veAddr != address(0)) {
// Get the total number of locks
_maxArrSize += IVestedFXS(_veAddr).numLocks(_account);
}
unchecked {
++i;
}
}
// Allocate a temporary dynamic array
uint256 _activeLockIdx = 0;
LockedBalanceExtendedV2[] memory _tmpActiveLocks = new LockedBalanceExtendedV2[](_maxArrSize);
// Go through the OG 3 sources first
// Fraxtal veFXS
// -------------------------
{
// Get the LockedBalanceExtendeds
LockedBalanceExtended[] memory _fxtlVeFXSLockedBalExtds = (veFXSUtils.getDetailedUserLockInfo(_account))
.activeLocks;
// Loop though the Fraxtal veFXS locks and add them to the combined array
for (uint256 i; i < _fxtlVeFXSLockedBalExtds.length; ) {
// Save tmp variable to memory
IveFXSStructs.LockedBalanceExtended memory _vestedFXSLockInfo = _fxtlVeFXSLockedBalExtds[i];
// (Optional) Estimate the lock's veFXS based on amount, end, and block.timestamp
uint256 _estimatedVeFXS;
if (_estimateCrudeVeFXS) {
_estimatedVeFXS = veFXSUtils.getCrudeExpectedVeFXSOneLock(
_vestedFXSLockInfo.amount,
_vestedFXSLockInfo.end - uint128(block.timestamp)
);
}
// Add to the temp array
_tmpActiveLocks[_activeLockIdx] = LockedBalanceExtendedV2({
id: _vestedFXSLockInfo.id,
index: _vestedFXSLockInfo.index,
amount: _vestedFXSLockInfo.amount,
end: _vestedFXSLockInfo.end,
location: address(veFXS),
estimatedCurrLockVeFXS: _estimatedVeFXS
});
// Increase the active lock index
++_activeLockIdx;
unchecked {
++i;
}
}
}
// (Optional) FPIS Locker
// -------------------------
if (address(fpisLocker) != address(0)) {
// Get the LockedBalanceExtendeds
IlFPISStructs.LockedBalanceExtended[] memory _fpisLockerLockedBalExtds = (
lFpisUtils.getDetailedUserLockInfo(_account)
).activeLocks;
// Loop though the FPIS Locker locks and add them to the combined array
for (uint256 i; i < _fpisLockerLockedBalExtds.length; ) {
// Save tmp variable to memory
IlFPISStructs.LockedBalanceExtended memory _fpisLockInfo = _fpisLockerLockedBalExtds[i];
// (Optional) Estimate the lock's veFXS based on amount, end, and block.timestamp
uint256 _estimatedVeFXS;
if (_estimateCrudeVeFXS) {
_estimatedVeFXS = lFpisUtils.getCrudeExpectedLFPISOneLock(
_fpisLockInfo.amount,
_fpisLockInfo.end - uint128(block.timestamp)
);
}
// Need to save as LockedBalanceExtendedV2
_tmpActiveLocks[_activeLockIdx] = LockedBalanceExtendedV2({
id: _fpisLockInfo.id,
index: _fpisLockInfo.index,
amount: _fpisLockInfo.amount,
end: _fpisLockInfo.end,
location: address(fpisLocker),
estimatedCurrLockVeFXS: _estimatedVeFXS
});
// Increase the active lock index
++_activeLockIdx;
unchecked {
++i;
}
}
}
// (Optional) L1VeFXS
// -------------------------
if ((address(l1veFXS) != address(0)) && (address(l1VeFXSTotalSupplyOracle) != address(0))) {
// Get the LockedBalance
IL1VeFXS.LockedBalance memory _l1LockedBalance = l1veFXS.locked(_account);
// Convert to LockedBalanceExtendedV2 and push into _currCombinedLockBalExtds if it is active. There is only one lock too
if (_l1LockedBalance.end > block.timestamp) {
// (Optional) Estimate the lock's veFXS based on amount, end, and block.timestamp
uint256 _estimatedVeFXS;
if (_estimateCrudeVeFXS) {
_estimatedVeFXS = l1veFXS.balanceOf(_account);
}
// Add to the temp array
_tmpActiveLocks[_activeLockIdx] = LockedBalanceExtendedV2({
id: 0,
index: 0,
amount: int128(_l1LockedBalance.amount),
end: _l1LockedBalance.end,
location: address(l1veFXS),
estimatedCurrLockVeFXS: _estimatedVeFXS
});
// Increase the active lock index
++_activeLockIdx;
}
}
// (Optional) Look in the extra veFXS sources next. They should all be IVestedFXS ABI compliant
for (uint256 i; i < addlVeContractsArr.length; ) {
address _veAddr = addlVeContractsArr[i];
if (_veAddr != address(0)) {
// Get the active locks
LockedBalanceExtended[] memory _addlVeFXSLockedBalExtds = (
IVestedFXSUtils(IVestedFXS(_veAddr).veFxsUtils()).getDetailedUserLockInfo(_account)
).activeLocks;
// Loop though the active locks and add them to the combined array
for (uint256 j; j < _addlVeFXSLockedBalExtds.length; ) {
// Save tmp variable to memory
IveFXSStructs.LockedBalanceExtended memory _addVeFXSLockInfo = _addlVeFXSLockedBalExtds[j];
// (Optional) Estimate the lock's veFXS based on amount, end, and block.timestamp
uint256 _estimatedVeFXS;
if (_estimateCrudeVeFXS) {
_estimatedVeFXS = IVestedFXSUtils(IVestedFXS(_veAddr).veFxsUtils())
.getCrudeExpectedVeFXSOneLock(
_addVeFXSLockInfo.amount,
_addVeFXSLockInfo.end - uint128(block.timestamp)
);
}
// Add to the temporary array
_tmpActiveLocks[_activeLockIdx] = LockedBalanceExtendedV2({
id: _addVeFXSLockInfo.id,
index: _addVeFXSLockInfo.index,
amount: _addVeFXSLockInfo.amount,
end: _addVeFXSLockInfo.end,
location: _veAddr,
estimatedCurrLockVeFXS: _estimatedVeFXS
});
// Increase the active lock index
++_activeLockIdx;
unchecked {
++j;
}
}
}
unchecked {
++i;
}
}
// Allocate the return array with only the number of active locks
_currActiveLocks = new LockedBalanceExtendedV2[](_activeLockIdx);
// Fill the return array
for (uint256 i; i < _currActiveLocks.length; ) {
_currActiveLocks[i] = _tmpActiveLocks[i];
unchecked {
++i;
}
}
}
/// @notice Get all the expired locks for a user
/// @param _account The account to get the locks for
/// @return _expiredLocks Array of LockedBalanceExtendedV2 structs (all expired locks)
/// @dev Technically could combine with getAllCurrActiveLocks to save gas, but getAllExpiredLocks is mainly intended for a UI
function getAllExpiredLocks(address _account) public view returns (LockedBalanceExtendedV2[] memory _expiredLocks) {
// Prepare to allocate the return array. Not all of the locks will be expired.
// OG 3 veFXS contracts
// ===================================
// Fraxtal VestedFXS
uint256 _maxArrSize = veFXS.numLocks(_account);
// (Optional) FPIS Locker
if (address(fpisLocker) != address(0)) _maxArrSize += fpisLocker.numLocks(_account);
// (Optional) L1VeFXS
if ((address(l1veFXS) != address(0)) && (address(l1VeFXSTotalSupplyOracle) != address(0))) {
_maxArrSize += 1; // Legacy veFXS on Mainnet only has one lock
}
// (Optional) Get the total number of locks in the additional veFXS contracts
for (uint256 i = 0; i < addlVeContractsArr.length; ) {
address _veAddr = addlVeContractsArr[i];
if (_veAddr != address(0)) {
// Get the total number of locks
_maxArrSize += IVestedFXS(_veAddr).numLocks(_account);
}
unchecked {
++i;
}
}
// Allocate a temporary dynamic array
uint256 _expiredLockIdx = 0;
LockedBalanceExtendedV2[] memory _tmpExpiredLocks = new LockedBalanceExtendedV2[](_maxArrSize);
// Go through the OG 3 sources first
// Fraxtal veFXS
// -------------------------
{
// Get the LockedBalanceExtendeds
LockedBalanceExtended[] memory _fxtlVeFXSLockedBalExtds = (veFXSUtils.getDetailedUserLockInfo(_account))
.expiredLocks;
// Loop though the Fraxtal veFXS locks and add them to the combined array
for (uint256 i; i < _fxtlVeFXSLockedBalExtds.length; ) {
// Save tmp variable to memory
IveFXSStructs.LockedBalanceExtended memory _vestedFXSLockInfo = _fxtlVeFXSLockedBalExtds[i];
// Add to the temp array
_tmpExpiredLocks[_expiredLockIdx] = LockedBalanceExtendedV2({
id: _vestedFXSLockInfo.id,
index: _vestedFXSLockInfo.index,
amount: _vestedFXSLockInfo.amount,
end: _vestedFXSLockInfo.end,
location: address(veFXS),
estimatedCurrLockVeFXS: 0
});
// Increase the expired lock index
++_expiredLockIdx;
unchecked {
++i;
}
}
}
// (Optional) FPIS Locker
// -------------------------
if (address(fpisLocker) != address(0)) {
// Get the LockedBalanceExtendeds
IlFPISStructs.LockedBalanceExtended[] memory _fpisLockerLockedBalExtds = (
lFpisUtils.getDetailedUserLockInfo(_account)
).expiredLocks;
// Loop though the FPIS Locker locks and add them to the combined array
for (uint256 i; i < _fpisLockerLockedBalExtds.length; ) {
// Save tmp variable to memory
IlFPISStructs.LockedBalanceExtended memory _fpisLockInfo = _fpisLockerLockedBalExtds[i];
// Need to save as LockedBalanceExtendedV2
_tmpExpiredLocks[_expiredLockIdx] = LockedBalanceExtendedV2({
id: _fpisLockInfo.id,
index: _fpisLockInfo.index,
amount: _fpisLockInfo.amount,
end: _fpisLockInfo.end,
location: address(fpisLocker),
estimatedCurrLockVeFXS: 0
});
// Increase the expired lock index
++_expiredLockIdx;
unchecked {
++i;
}
}
}
// (Optional) L1VeFXS
// -------------------------
if ((address(l1veFXS) != address(0)) && (address(l1VeFXSTotalSupplyOracle) != address(0))) {
// Get the LockedBalance
IL1VeFXS.LockedBalance memory _l1LockedBalance = l1veFXS.locked(_account);
// Convert to LockedBalanceExtendedV2 and push into _currCombinedLockBalExtds if it is expired. There is only one lock too
if (_l1LockedBalance.end <= block.timestamp) {
// Add to the temp array
_tmpExpiredLocks[_expiredLockIdx] = LockedBalanceExtendedV2({
id: 0,
index: 0,
amount: int128(_l1LockedBalance.amount),
end: _l1LockedBalance.end,
location: address(l1veFXS),
estimatedCurrLockVeFXS: 0
});
// Increase the expired lock index
++_expiredLockIdx;
}
}
// (Optional) Look in the extra veFXS sources next. They should all be IVestedFXS ABI compliant
for (uint256 i; i < addlVeContractsArr.length; ) {
address _veAddr = addlVeContractsArr[i];
if (_veAddr != address(0)) {
// Get the expired locks
LockedBalanceExtended[] memory _addlVeFXSLockedBalExtds = (
IVestedFXSUtils(IVestedFXS(_veAddr).veFxsUtils()).getDetailedUserLockInfo(_account)
).expiredLocks;
// Loop though the expired locks and add them to the combined array
for (uint256 j; j < _addlVeFXSLockedBalExtds.length; ) {
// Save tmp variable to memory
IveFXSStructs.LockedBalanceExtended memory _addVeFXSLockInfo = _addlVeFXSLockedBalExtds[j];
// Add to the temporary array
_tmpExpiredLocks[_expiredLockIdx] = LockedBalanceExtendedV2({
id: _addVeFXSLockInfo.id,
index: _addVeFXSLockInfo.index,
amount: _addVeFXSLockInfo.amount,
end: _addVeFXSLockInfo.end,
location: _veAddr,
estimatedCurrLockVeFXS: 0
});
// Increase the expired lock index
++_expiredLockIdx;
unchecked {
++j;
}
}
}
unchecked {
++i;
}
}
// Allocate the return array with only the number of expired locks
_expiredLocks = new LockedBalanceExtendedV2[](_expiredLockIdx);
// Fill the return array
for (uint256 i; i < _expiredLocks.length; ) {
_expiredLocks[i] = _tmpExpiredLocks[i];
unchecked {
++i;
}
}
}
// ==============================================================================
// MUTATIVE FUNCTIONS
// ==============================================================================
// None...
// ==============================================================================
// RESTRICTED FUNCTIONS
// ==============================================================================
/// @notice Adds an additional veFXS-like contract
/// @param _addr The contract to added
function addAddlVeFXSContract(address _addr) public onlyByOwnGov {
require(_addr != address(0), "Zero address detected");
// Check the ABI here to make sure it is veFXS-like
// None of these should revert
IVestedFXS(_addr).totalSupply();
IVestedFXS(_addr).balanceOf(address(0));
IVestedFXS(_addr).numLocks(address(0));
IVestedFXSUtils(IVestedFXS(_addr).veFxsUtils()).getDetailedUserLockInfo(address(0));
IVestedFXSUtils(IVestedFXS(_addr).veFxsUtils()).getCrudeExpectedVeFXSOneLock(1e18, 604_800);
require(addlVeContracts[_addr] == false, "Address already exists");
addlVeContracts[_addr] = true;
addlVeContractsArr.push(_addr);
emit AddlVeFXSContractAdded(_addr);
}
/// @notice Removes a veFXS-like contract. Will need to mass checkpoint on the yield distributor or other sources to reflect new stored total veFXS
/// @param _addr The contract to remove
function removeAddlVeFXSContract(address _addr) public onlyByOwnGov {
require(_addr != address(0), "Zero address detected");
require(addlVeContracts[_addr] == true, "Address nonexistent");
// Delete from the mapping
delete addlVeContracts[_addr];
// 'Delete' from the array by setting the address to 0x0
for (uint256 i = 0; i < addlVeContractsArr.length; i++) {
if (addlVeContractsArr[i] == _addr) {
addlVeContractsArr[i] = address(0); // This will leave a null in the array and keep the indices the same
break;
}
}
emit AddlVeFXSContractRemoved(_addr);
}
/// @notice Added to support recovering LP Yield and other mistaken tokens from other systems to be distributed to holders
/// @param _tokenAddress The token to recover
/// @param _tokenAmount The amount to recover
function recoverERC20(address _tokenAddress, uint256 _tokenAmount) external onlyByOwnGov {
// Only the owner address can ever receive the recovery withdrawal
TransferHelper.safeTransfer(_tokenAddress, owner, _tokenAmount);
emit RecoveredERC20(_tokenAddress, _tokenAmount);
}
/// @notice Set the original 3 veFXS-like contracts on Fraxtal
/// @param _veAddresses The addresses: 0: veFXS, 1: veFXSUtils, 2: FPIS Locker, 3: FPISLockerUtils, 4: L1VeFXS, 5: L1VeFXSTotalSupplyOracle
function setAddresses(address[6] calldata _veAddresses) external onlyByOwnGov {
// Future upgrade: remove this once full support is added and tested
require(_veAddresses[0] != address(0), "veFXS must not be 0x0");
require(_veAddresses[1] != address(0), "veFXSUtils must not be 0x0");
require(_veAddresses[2] != address(0), "FPISLocker must not be 0x0");
require(_veAddresses[3] != address(0), "FPISLockerUtils must not be 0x0");
require(_veAddresses[4] != address(0), "L1VeFXS must not be 0x0");
require(_veAddresses[5] != address(0), "L1VeFXSTotalSupplyOracle must not be 0x0");
// Set veFXS-like addresses
veFXS = IVestedFXS(_veAddresses[0]);
veFXSUtils = IVestedFXSUtils(_veAddresses[1]);
// FPIS Locker
if ((_veAddresses[2] != address(0)) && _veAddresses[3] != address(0)) {
fpisLocker = IFPISLocker(_veAddresses[2]);
lFpisUtils = FPISLockerUtils(_veAddresses[3]);
}
// L1VeFXS and L1VeFXSTotalSupplyOracle
if ((_veAddresses[4] != address(0)) && (_veAddresses[5] != address(0))) {
l1veFXS = IL1VeFXS(_veAddresses[4]);
l1VeFXSTotalSupplyOracle = L1VeFXSTotalSupplyOracle(_veAddresses[5]);
}
}
/// @notice Set the timelock address
/// @param _newTimelock The address of the timelock
function setTimelock(address _newTimelock) external onlyByOwnGov {
timelockAddress = _newTimelock;
emit TimelockChanged(_newTimelock);
}
// ==============================================================================
// EVENTS
// ==============================================================================
/// @notice When an additional veFXS contract is added
/// @param addr The contract that was added
event AddlVeFXSContractAdded(address addr);
/// @notice When an additional veFXS contract is removed
/// @param addr The contract that was removed
event AddlVeFXSContractRemoved(address addr);
/// @notice When the contract is initialized
event DefaultInitialization();
/// @notice When ERC20 tokens were recovered
/// @param token Token address
/// @param amount Amount of tokens collected
event RecoveredERC20(address token, uint256 amount);
/// @notice When a reward is deposited
/// @param reward Amount of tokens deposited
/// @param yieldRate The resultant yield/emission rate
event RewardAdded(uint256 reward, uint256 yieldRate);
/// @notice Emitted when the timelock address changes
/// @param timelock_address Address of the removed timelock
event TimelockChanged(address timelock_address);
/// @notice When yield is collected
/// @param user Address collecting the yield
/// @param yield The amount of tokens collected
/// @param tokenAddress The address collecting the rewards
event YieldCollected(address indexed user, uint256 yield, address tokenAddress);
/// @notice When the yield duration is updated
/// @param newDuration The new duration
event YieldDurationUpdated(uint256 newDuration);
// ==============================================================================
// ERRORS
// ==============================================================================
/// @notice Cannot initialize twice
error InitializeFailed();
/// @notice If you are trying to call a function not as the owner or timelock
error NotOwnerOrTimelock();
}
// src/contracts/VestedFXS-and-Flox/VestedFXS/YieldDistributor.sol
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// =========================YieldDistributor===========================
// ====================================================================
// Distributes Frax protocol yield based on the claimer's veFXS balance
// Yield will now not accrue for unlocked veFXS
// Frax Finance: https://github.com/FraxFinance
// Primary Author(s)
// Jan Turk: https://github.com/ThunderDeliverer
// Travis Moore: https://github.com/FortisFortuna
// Reviewer(s) / Contributor(s)
// Sam Kazemian: https://github.com/samkazemian
// Originally inspired by Synthetix.io, but heavily modified by the Frax team (veFXS portion)
// https://github.com/Synthetixio/synthetix/blob/develop/contracts/StakingRewards.sol
// import "forge-std/console2.sol";
contract YieldDistributor is OwnedV2AutoMsgSender, ReentrancyGuard, IveFXSStructs {
using SafeERC20 for ERC20;
// ==============================================================================
// STATE VARIABLES
// ==============================================================================
// Instances
// -------------------------
/// @notice Aggregator contract that sums a user's veFXS from multiple sources
VeFXSAggregator public veFXSAggregator;
/// @notice ERC20 instance of the token being emitted
ERC20 public emittedToken;
// Addresses
// -------------------------
/// @notice Address of the token being emitted
address public emittedTokenAddress;
/// @notice Address of the timelock
address public timelockAddress;
// Yield and period related
// -------------------------
/// @notice Timestamp when the reward period ends
uint256 public periodFinish;
/// @notice Timestamp when the contract was last synced or had rewards deposited
uint256 public lastUpdateTime;
/// @notice Emission rate of tokens, in tokens per second
uint256 public yieldRate;
/// @notice Duration of the period, in seconds
uint256 public yieldDuration; // 7 * 86400 (7 days)
/// @notice Mapping of addresses that are allowed to deposit reward tokens
mapping(address => bool) public rewardNotifiers;
// Yield tracking
// -------------------------
/// @notice Accumulator for tracking contract-wide rewards paid
uint256 public yieldPerVeFXSStored;
/// @notice Accumulator for tracking user-specific rewards paid
mapping(address => uint256) public userYieldPerTokenPaid;
/// @notice Last stored version of earned(). Set to 0 on yield claim and to earned() on a checkpoint.
mapping(address => uint256) public yields;
// veFXS tracking
// -------------------------
/// @notice Total amount of veFXS that was checkpointed and is earning
uint256 public totalVeFXSParticipating;
/// @notice Stored version of the total veFXS supply
uint256 public totalComboVeFXSSupplyStored;
/// @notice If the user was initialized or not
mapping(address => bool) public userIsInitialized;
/// @notice Last stored veFXS balance for the user
mapping(address => uint256) public userVeFXSCheckpointed;
/// @notice The stored shortest endpoint of any of the user's veFXS positions. You will need to re-checkpoint after any lock expires if you want to keep earning.
mapping(address => uint256) public userVeFXSEndpointCheckpointed;
/// @notice Last time the user claimed their yield
mapping(address => uint256) private lastRewardClaimTime; // staker addr -> timestamp
// Greylists
// -------------------------
/// @notice A graylist for questionable users
mapping(address => bool) public greylist;
// Constants
// -------------------------
/// @notice Constant for price precision
uint256 private constant PRICE_PRECISION = 1e6;
// Admin related
// -------------------------
/// @notice For Convex, StakeDAO, etc whose contract addresses cannot claim for themselves. Admin set on a case-by-case basis
mapping(address staker => address claimer) public thirdPartyClaimers;
/// @notice A graylist for questionable users
bool public yieldCollectionPaused = false; // For emergencies
// Misc
// -------------------------
/// @notice If the contract was initialized
bool wasInitialized;
// Gap
// -------------------------
/// @dev reserve extra storage for future upgrades
uint256[50] private __gap;
// ==============================================================================
// MODIFIERS
// ==============================================================================
/// @notice A modifier that only allows the contract owner or the timelock to call
modifier onlyByOwnGov() {
if (msg.sender != owner && msg.sender != timelockAddress) revert NotOwnerOrTimelock();
_;
}
/// @notice Make sure yield collection is not paused
modifier notYieldCollectionPaused() {
if (yieldCollectionPaused) revert YieldCollectionPaused();
_;
}
/// @notice Checkpoint the user
modifier checkpointUser(address account) {
_checkpointUser(account, true);
_;
}
// ==============================================================================
// CONSTRUCTOR
// ==============================================================================
constructor() {
// Set the contract as initialized
wasInitialized = true;
}
/// @notice Initialize contract
/// @param _owner The owner of this contract
/// @param _timelockAddress Address of the timelock
/// @param _emittedToken Address of the token being emitted as yield
/// @param _veFXSAggregator Address of the veFXS aggregator
function initialize(
address _owner,
address _timelockAddress,
address _emittedToken,
address _veFXSAggregator
) public {
// Safety checks - no validation on admin in case this is initialized without admin
if (wasInitialized || _emittedToken == address(0) || emittedTokenAddress != address(0)) {
revert InitializeFailed();
}
// Set owner for OwnedV2
owner = _owner;
// Set misc addresses
emittedTokenAddress = _emittedToken;
emittedToken = ERC20(_emittedToken);
timelockAddress = _timelockAddress;
// Set the veFXS Aggregator
veFXSAggregator = VeFXSAggregator(_veFXSAggregator);
// Initialize other variables
lastUpdateTime = block.timestamp;
rewardNotifiers[_owner] = true;
yieldDuration = 604_800;
// Set the contract as initialized
wasInitialized = true;
}
// ==============================================================================
// VIEWS
// ==============================================================================
/// @notice Fraction of the total Fraxtal-visible veFXS collecting yield
/// @return _fraction The Fraction
function fractionParticipating() external view returns (uint256 _fraction) {
if (totalComboVeFXSSupplyStored == 0) return 0;
else return (totalVeFXSParticipating * PRICE_PRECISION) / totalComboVeFXSSupplyStored;
}
/// @notice Eligible veFXS for a given user. Only positions with locked veFXS can accrue yield, not expired positions
/// @param _user The user to check
/// @return _eligibleVefxsBal Eligible veFXS
/// @return _storedEndingTimestamp The stored ending timestamp
function eligibleCurrentVeFXS(
address _user
) public view returns (uint256 _eligibleVefxsBal, uint256 _storedEndingTimestamp) {
// Get the total combined veFXS from all sources
uint256 _currVefxsBal = veFXSAggregator.ttlCombinedVeFXS(_user);
// Stored is used to prevent abuse
_storedEndingTimestamp = userVeFXSEndpointCheckpointed[_user];
// Only unexpired veFXS should be eligible
if (block.timestamp >= _storedEndingTimestamp) {
_eligibleVefxsBal = 0;
} else {
_eligibleVefxsBal = _currVefxsBal;
}
}
/// @notice Last time the yield was accruing
/// @return _ts The timestamp
function lastTimeYieldApplicable() public view returns (uint256 _ts) {
return (block.timestamp < periodFinish ? block.timestamp : periodFinish);
}
/// @notice Amount of yield per veFXS
/// @return _yield The amount of yield
function yieldPerVeFXS() public view returns (uint256 _yield) {
if (totalComboVeFXSSupplyStored == 0) {
return yieldPerVeFXSStored;
} else {
return (yieldPerVeFXSStored +
(((lastTimeYieldApplicable() - lastUpdateTime) * yieldRate * 1e18) / totalComboVeFXSSupplyStored));
}
}
/// @notice Amount of tokens claimaible as yield
/// @param _account The user to check
/// @return _earned The amount of yield
function earned(address _account) public view returns (uint256 _earned) {
// Uninitialized users should not earn anything yet
// console2.log("userIsInitialized[_account]: ", userIsInitialized[_account]);
if (!userIsInitialized[_account]) return 0;
// Get eligible veFXS balances
(uint256 eligibleCurrentVefxs, uint256 endingTimestamp) = eligibleCurrentVeFXS(_account);
// If your veFXS is unlocked
uint256 eligibleTimeFraction = PRICE_PRECISION;
// console2.log("eligibleTimeFraction: ", eligibleTimeFraction);
if (eligibleCurrentVefxs == 0) {
// console2.log("block.timestamp: ", block.timestamp);
// console2.log("lastRewardClaimTime[_account]: ", lastRewardClaimTime[_account]);
// console2.log("endingTimestamp: ", endingTimestamp);
// And you already claimed after expiration
if (lastRewardClaimTime[_account] >= endingTimestamp) {
// You get NOTHING. You LOSE. Good DAY ser!
return 0;
}
// You haven't claimed yet
else {
// See what fraction of the time since you last claimed that you were eligible for earning
// console2.log("calculating eligibleTimeFraction");
uint256 eligibleTime = endingTimestamp - lastRewardClaimTime[_account];
// console2.log("eligibleTime: ", eligibleTime);
uint256 totalTime = block.timestamp - lastRewardClaimTime[_account];
// console2.log("totalTime: ", totalTime);
eligibleTimeFraction = (PRICE_PRECISION * eligibleTime) / totalTime;
// console2.log("eligibleTimeFraction: ", eligibleTimeFraction);
}
}
// If the amount of veFXS increased, only pay off based on the old balance
// Otherwise, take the midpoint
uint256 vefxsBalanceToUse;
uint256 oldVefxsBalance = userVeFXSCheckpointed[_account];
// console2.log("vefxsBalanceToUse: ", vefxsBalanceToUse);
// console2.log("oldVefxsBalance: ", oldVefxsBalance);
if (eligibleCurrentVefxs > oldVefxsBalance) {
// VeFXS increased so use old amount
vefxsBalanceToUse = oldVefxsBalance;
// console2.log("VeFXS increased so use old amount: ", vefxsBalanceToUse);
} else {
// VeFXS decreased so use midpoint (average)
vefxsBalanceToUse = (eligibleCurrentVefxs + oldVefxsBalance) / 2;
// console2.log("VeFXS decreased so use midpoint (average): ", vefxsBalanceToUse);
// Print old earnings if there was no midpointing (debug only)
// uint256 _oldVeFXSEarnings = ((oldVefxsBalance *
// (yieldPerVeFXS() - userYieldPerTokenPaid[_account]) *
// eligibleTimeFraction) /
// (1e18 * PRICE_PRECISION) +
// yields[_account]);
// console2.log("Old earnings would have been: ", _oldVeFXSEarnings);
}
// Calculate earnings
return ((vefxsBalanceToUse * (yieldPerVeFXS() - userYieldPerTokenPaid[_account]) * eligibleTimeFraction) /
(1e18 * PRICE_PRECISION) +
yields[_account]);
}
/// @notice Total amount of yield for the duration (normally a week)
/// @return _yield The amount of yield
function getYieldForDuration() external view returns (uint256 _yield) {
return (yieldRate * yieldDuration);
}
// ==============================================================================
// MUTATIVE FUNCTIONS
// ==============================================================================
/// @notice Checkpoint a user's earnings
/// @param _account The user to checkpoint
/// @param _syncToo Should normally be true. Can be false only for bulkCheckpointOtherUsers to save gas since it calls sync() once beforehand
/// @dev If you want to keep earning, you need to make sure you checkpoint after ANY lock expires
function _checkpointUser(address _account, bool _syncToo) internal {
// Need to retro-adjust some things if the period hasn't been renewed, then start a new one
// Should always sync unless you are bulkCheckpointOtherUsers, which can be called once beforehand to save gas
if (_syncToo) sync();
// Calculate the earnings first
_syncEarned(_account);
// Get the old and the new veFXS balances
uint256 _oldVefxsBalance = userVeFXSCheckpointed[_account];
// Get the total combined veFXS from all sources
uint256 _newVefxsBalance = veFXSAggregator.ttlCombinedVeFXS(_account);
// Update the user's stored veFXS balance
userVeFXSCheckpointed[_account] = _newVefxsBalance;
// Collect all active locks
LockedBalanceExtendedV2[] memory _currCombinedLockBalExtds = veFXSAggregator.getAllCurrActiveLocks(
_account,
false
);
// Update the user's stored ending timestamp
// TODO: Check this math as well as corner cases
// TODO: Is there a better way to do this? This might be ok for now since gas is low on Fraxtal, but in the future,
// I imagine there is a more elegant solution
// ----------------------
uint128 _shortestActiveLockEnd;
// In case there are no active locks anywhere
if (_currCombinedLockBalExtds.length > 0) {
// console2.log("_checkpointUser > 0 active locks");
_shortestActiveLockEnd = _currCombinedLockBalExtds[0].end;
}
// Find the timestamp of the lock closest to expiry
if (_currCombinedLockBalExtds.length > 1) {
// console2.log("_checkpointUser > 1 active locks");
for (uint256 i; i < _currCombinedLockBalExtds.length; ) {
// console2.log("_currCombinedLockBalExtds[i].end: ", _currCombinedLockBalExtds[i].end);
if (_currCombinedLockBalExtds[i].end < _shortestActiveLockEnd) {
_shortestActiveLockEnd = _currCombinedLockBalExtds[i].end;
}
unchecked {
++i;
}
}
}
// console2.log("userVeFXSEndpointCheckpointed result: ", _shortestActiveLockEnd);
userVeFXSEndpointCheckpointed[_account] = _shortestActiveLockEnd;
// Update the total amount participating
if (_newVefxsBalance >= _oldVefxsBalance) {
uint256 weightDiff = _newVefxsBalance - _oldVefxsBalance;
totalVeFXSParticipating = totalVeFXSParticipating + weightDiff;
} else {
uint256 weightDiff = _oldVefxsBalance - _newVefxsBalance;
totalVeFXSParticipating = totalVeFXSParticipating - weightDiff;
}
// Mark the user as initialized
if (!userIsInitialized[_account]) {
userIsInitialized[_account] = true;
lastRewardClaimTime[_account] = block.timestamp;
}
}
/// @notice Sync a user's earnings
/// @param _account The user to sync
function _syncEarned(address _account) internal {
if (_account != address(0)) {
uint256 earned0 = earned(_account);
yields[_account] = earned0;
userYieldPerTokenPaid[_account] = yieldPerVeFXSStored;
}
}
/// @notice Anyone can checkpoint another user
/// @param _account The user to sync
function checkpointOtherUser(address _account) external {
_checkpointUser(_account, true);
}
/// @notice Anyone can checkpoint other users
/// @param _accounts The users to sync
function bulkCheckpointOtherUsers(address[] memory _accounts) external {
// Loop through the addresses
for (uint256 i = 0; i < _accounts.length; ) {
// Sync once to save gas
sync();
// Can skip syncing here since you did it above
_checkpointUser(_accounts[i], false);
unchecked {
++i;
}
}
}
/// @notice Checkpoint yourself
function checkpoint() external {
_checkpointUser(msg.sender, true);
}
/// @notice Retrieve yield for a specific address and send it to the designed recipient
/// @param _staker The address whose rewards to collect
/// @param _recipient Recipient of the rewards
/// @return _yield0 The amount collected
function _getYield(
address _staker,
address _recipient
) internal nonReentrant notYieldCollectionPaused checkpointUser(_staker) returns (uint256 _yield0) {
if (greylist[_staker]) revert AddressGreylisted();
_yield0 = yields[_staker];
if (_yield0 > 0) {
yields[_staker] = 0;
TransferHelper.safeTransfer(emittedTokenAddress, _recipient, _yield0);
emit YieldCollected(_staker, _recipient, _yield0, emittedTokenAddress);
}
lastRewardClaimTime[_staker] = block.timestamp;
}
/// @notice Retrieve own yield
/// @return _yield0 The amount collected
function getYield() external returns (uint256 _yield0) {
// Sender collects rewards for himself
_yield0 = _getYield(msg.sender, msg.sender);
}
/// @notice Retrieve another address's yield. Only for specific cases (e.g. Convex, etc) where the mainnet contract cannot claim for itself
/// @param _staker Address whose rewards to collect
/// @return _yield0 The amount collected
/// @dev Only specific addresses allowed by the admin can do this, and only 1:1 (i.e. the third party can only collect one specified address's rewards)
function getYieldThirdParty(address _staker) external returns (uint256 _yield0) {
// Make sure the sender is authorized for this _staker
if (thirdPartyClaimers[_staker] != msg.sender) revert SenderNotAuthorizedClaimer();
// Sender collects _staker's rewards and sends to himself
_yield0 = _getYield(_staker, msg.sender);
}
/// @notice Sync contract-wide variables
function sync() public {
// Update the yieldPerVeFXSStored
// console2.log("Update the yieldPerVeFXSStored");
yieldPerVeFXSStored = yieldPerVeFXS();
// Update the total veFXS supply
// console2.log("Update the totalComboVeFXSSupplyStored");
totalComboVeFXSSupplyStored = veFXSAggregator.ttlCombinedVeFXSTotalSupply();
// Update the last update time
// console2.log("Update the lastUpdateTime");
lastUpdateTime = lastTimeYieldApplicable();
// console2.log("Sync completed");
}
/// @notice Deposit rewards. Only callable by privileged users
/// @param _amount The amount to deposit
function notifyRewardAmount(uint256 _amount) external {
// Only whitelisted addresses can notify rewards
if (!rewardNotifiers[msg.sender]) revert SenderNotRewarder();
// Handle the transfer of emission tokens via `transferFrom` to reduce the number
// of transactions required and ensure correctness of the emission amount
emittedToken.safeTransferFrom(msg.sender, address(this), _amount);
// Update some values beforehand
sync();
// Update the new yieldRate
if (block.timestamp >= periodFinish) {
yieldRate = _amount / yieldDuration;
} else {
uint256 remaining = periodFinish - block.timestamp;
uint256 leftover = remaining * yieldRate;
yieldRate = (_amount + leftover) / yieldDuration;
}
// Update duration-related info
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp + yieldDuration;
// Update some values afterwards
totalComboVeFXSSupplyStored = veFXSAggregator.ttlCombinedVeFXSTotalSupply();
emit RewardAdded(_amount, yieldRate);
}
// ==============================================================================
// RESTRICTED FUNCTIONS
// ==============================================================================
/// @notice Added to support recovering LP Yield and other mistaken tokens from other systems to be distributed to holders
/// @param _tokenAddress The token to recover
/// @param _tokenAmount The amount to recover
function recoverERC20(address _tokenAddress, uint256 _tokenAmount) external onlyByOwnGov {
// Only the owner address can ever receive the recovery withdrawal
TransferHelper.safeTransfer(_tokenAddress, owner, _tokenAmount);
emit RecoveredERC20(_tokenAddress, _tokenAmount);
}
/// @notice Set the duration of the yield
/// @param _yieldDuration New duration in seconds
function setYieldDuration(uint256 _yieldDuration) external onlyByOwnGov {
if (periodFinish != 0 && block.timestamp <= periodFinish) {
revert YieldPeriodMustCompleteBeforeChangingToNewPeriod();
}
yieldDuration = _yieldDuration;
emit YieldDurationUpdated(yieldDuration);
}
/// @notice Greylist an address that is misbehaving
/// @dev This is a toggle, so it can re-enable to user as well
/// @param _address The address to greylist
function greylistAddress(address _address) external onlyByOwnGov {
greylist[_address] = !(greylist[_address]);
}
/// @notice Toggle an address as being able to be a reward notifier
/// @param _notifierAddr The address to toggle
function toggleRewardNotifier(address _notifierAddr) external onlyByOwnGov {
rewardNotifiers[_notifierAddr] = !rewardNotifiers[_notifierAddr];
}
/// @notice Set the veFXS Aggregator contract
/// @param _veFXSAggregator The new address of the veFXS Aggregator
function setVeFXSAggregator(address _veFXSAggregator) external onlyByOwnGov {
veFXSAggregator = VeFXSAggregator(_veFXSAggregator);
}
/// @notice Pause / unpause yield collecting
/// @param _yieldCollectionPaused The new status
function setPauses(bool _yieldCollectionPaused) external onlyByOwnGov {
yieldCollectionPaused = _yieldCollectionPaused;
}
/// @notice Used for manual reward rates. Only valid until the next notifyRewardAmount() or setYieldRate()
/// @param _newRate The new rate
/// @param _syncToo Whether to sync or not
function setYieldRate(uint256 _newRate, bool _syncToo) external onlyByOwnGov {
yieldRate = _newRate;
if (_syncToo) {
sync();
}
}
/// @notice Allow a 3rd party address to claim the rewards of a specific staker
/// @param _staker The address of the staker
/// @param _claimer The address of the claimer
/// @dev For Convex, StakeDAO, etc whose contract addresses cannot claim for themselves. Admin set on a case-by-case basis
function setThirdPartyClaimer(address _staker, address _claimer) external onlyByOwnGov {
thirdPartyClaimers[_staker] = _claimer;
}
/// @notice Set the timelock address
/// @param _newTimelock The address of the timelock
function setTimelock(address _newTimelock) external onlyByOwnGov {
timelockAddress = _newTimelock;
emit TimelockChanged(_newTimelock);
}
// ==============================================================================
// EVENTS
// ==============================================================================
/// @notice When the contract is initialized
event DefaultInitialization();
/// @notice When ERC20 tokens were recovered
/// @param token Token address
/// @param amount Amount of tokens collected
event RecoveredERC20(address token, uint256 amount);
/// @notice When a reward is deposited
/// @param reward Amount of tokens deposited
/// @param yieldRate The resultant yield/emission rate
event RewardAdded(uint256 reward, uint256 yieldRate);
/// @notice Emitted when the timelock address changes
/// @param timelock_address Address of the removed timelock
event TimelockChanged(address timelock_address);
/// @notice When yield is collected
/// @param staker Address whose rewards to collect
/// @param recipient Address where the yield is ultimately sent
/// @param yield The amount of tokens collected
/// @param tokenAddress The address collecting the rewards
event YieldCollected(address indexed staker, address indexed recipient, uint256 yield, address tokenAddress);
/// @notice When the yield duration is updated
/// @param newDuration The new duration
event YieldDurationUpdated(uint256 newDuration);
// ==============================================================================
// ERRORS
// ==============================================================================
/// @notice If the address was greylisted
error AddressGreylisted();
/// @notice Cannot initialize twice
error InitializeFailed();
/// @notice If you are trying to call a function not as the owner or timelock
error NotOwnerOrTimelock();
/// @notice If the sender is not an authorized thirdPartyClaimers for the specified staker address
error SenderNotAuthorizedClaimer();
/// @notice If the sender is not a rewarder
error SenderNotRewarder();
/// @notice If yield collection is paused
error YieldCollectionPaused();
/// @notice If you are trying to change a yield period before it ends
error YieldPeriodMustCompleteBeforeChangingToNewPeriod();
/* ====================================== A NIFFLER ================================================ */
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0OxdOKKOOkxxxxxxk0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0dl:,',cc:;;;;;;;;,'';cx0XWMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXkl:;::::::::::;;;;:::::;;,;cox0NWMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXxc;;:;;;;;;;,;,,,,,,,,,;,,,,,,,,;cdOXMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWOc;;;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'.;d0NMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXd;;:;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'',l0WMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXo;;;,,,,,,,,,,,,,,,,,,,,,,''''''',,,,,,,,,,ckNMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNd;;,,,,,,,,,,,,,,,,,,,,,,,'''''...'',,,,,,,,,,l0WMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'''''',,,,,,,'.'xNMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNo',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'.'kWMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM0:',,,,,,,,,,,,,,,;;;,,,,,,,,,,,,,,,,,,,,,,,,,,,,''lKMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO;',,;;,,,,,,,;:cc:;:c;,,,,,,,,,,,,,,,,,,,,,,,,,,,,'c0WMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMk,';lkkxoc;,,,cxl,...cl,,,,,,,,,,,,,,,,,,,,,,,,,,,,'':OWMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx;cx00000OkdooxOd;',;ll,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'.;OWMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKOxdxO00000000000000Oxxxd:,,''',,,,,,,,,,,,,,,,,,,,,,,,'..,OWMMMMMMM
// MMMMMMMMMMMMMMMMMMMMWKkkOO00OOkxxxO00000000000000000Okddd:.....'''''',,,,,,,,,,,,,,,,,,,'..oNMMMMMMM
// MMMMMMMMMMMMMMMMMMMM0ookkxxxdxk00000000000000000Okkkxxdl;............',,,,,,,,,,,,,,,,,,'..;OMMMMMMM
// MMMMMMMMMMMMMMMMMMMMKdoxOOOO000000000000000Okkxdollc:;'.....''..''....',,,,,,,,,,,,,,,,,,'..;KMMMMMM
// MMMMMMMMMMMMMMMMMMMMMNOxddodddxxxxxxxxddoll:,,,,,'''''''.'',,''',,'','',,,,,,,,,,,,,,,,,,,'..dNMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMNXK0OOOkkkkkkkOkdc;'.',,,,,,''''',,,,,,,,,,,,,,,,,,,,,',,,,,,,,,,,,.,xNMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKko:;:lodxxxxxdolc;,,,,,,,,,,,,,,,,,,,'''',,,,,,,,,,,,''dWMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKkddl:lxO000000000000Odc;,,,,,,,,,,,,,,'.',,,,,,,,,,,,,,,,.:KMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0odO0kooxO00000000000000Oxl:::::::;;;::,.',,,,,,,,,,,,,,,,,',kMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWNXdlk0kdodO000000000000000kxdxOOOOOkkkkOkxc,',,,,,,,,,,,,,,,,'.dWMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMWNKkdoccol:loc:;:lllllllooddxkOOOdllok0OO0000000Od;',,,,,,,,,,,,,,,,'.lNMMMM
// MMMMMMMMMMMMMMMMMMMMMMMKl:c::c:;,,','',,,,,,,,,,,,,,,;:cllcc::::::clodxxdc,',,,'''..'',,,,,,'.cXMMMM
// MMMMMMMMMMMMMMMMMMMMMMXo:clc:;,,,,,,,,,,,,,,,,,,,,,,,,,,,,;;,''''''''''''..........',,,,,,,,..cXMMMM
// MMMMMMMMMMMMMMMMMMMMMMOlol,'',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''''''''....''''''',,,,,,,,,,,,,..lNMMMM
// MMMMMMMMMMMMMMMMMMMMMMk:;,,,,,,,,,,,,,,,,,,,,,,,:,',,,,,,,''..............'',,,,,,,,,,,,,,,,..dWMMMM
// MMMMWWWMWWMMMMMMMMMMMXl'',,,,,,,,,,,,,,,,;:;:olcdocl:'''.....'',,,,,,''',''..',,,,,,,,,,,,,'.;0MMMMM
// MMMMXdlxllkXWMNXWMMMNo..,,,,,,,,,,,,,,,,,:oxoxkxkOOOl'....'',,,,,,,,,,,,,,,,'.'',,,,,,,,,,'..oWMMMMM
// MMMMWk,...';ldc,lxk0k;.',,,,,,,,,,,,,,,,,;ckOOO00000l..'',,,,,,,,,,,,,,,,,,,,,'',,,,,,,,,,..'kMMMMMM
// MMMMMNl..,,,,'''''',,'....'',,,,,,,,,,,,cook0000000Oc..',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'..;0MMMMMM
// MMMMMMO...',,,,,,,,,,,'.'''..''',,,,,,,,lkkO000000Ox;.',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...lNMMMMMM
// MMMMMMNl....'',,,,,,,,,,,,,,''''..',,,,;dkO00000xlc:,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'..'kMMMMMMM
// MMMMMMMk'....',,,,,,,,,,,,,,,,,''..'',,:xkO000Oxc,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'...cXMMMMMMM
// MMMMMMMX:....'',,,,,,,,,,,,,,,,,,''..''cxkO0Oxl:,,,,,,,,,,,,,,,,,,,,,,',,,,,,,,,,,,,,,'..,o0MMMMMMMM
// MMMMMMMM0,.....'',,,,,,,,,,,,,,,,,,,'.':xkOOd;'',,,,,,,,,,,,,,,,,,,,'''',,,,,,,,,,,,,'..'kWMMMMMMMMM
// MMMMMMMMW0;......'',,,,,,,,,,,,,,,,,,'';dkkd:,,,,,,,,,,,,,,,,,,,,,,'''',,,,,,,,,,,,,'..'xWMMMMMMMMMM
// MMMMMMMMMMKl.......'',,,,,,,,,,,,,,,,,,,cdl;,,,,,,,,,,,,,,,,,,,,'''''',,,,,,,,,,,,,'..'xNMMMMMMMMMMM
// MMMMMMMMMMMNx,.......''',,,,,,,,,,,,,,,',;,',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''...;OWMMMMMMMMMMMM
// MMMMMMMMMMMMNk;..........'',,,,,,,,,,,,,'..',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'....'oXMMMMMMMMMMMMMM
// MMMMMMMMMMMMMWXx;.......'',,,,,,,,,,,,,,'..',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'....'l0WMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMN0o;......''''''''',,,,,,''',,,,,,,,,,,,,,,,,,,,,''',,,,,''....'l0WMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMNk:..............'''''','',,,,,,,,,,,,,,,,'''...''''...':ccdKWMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMN0dc;'..................''''''''''''''..........';cokKNNNMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMNX0Okxddoolc::;,'............''','...',:loxOKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWNXK0OOOkkkkkOOO0KKK000KXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressGreylisted","type":"error"},{"inputs":[],"name":"InitializeFailed","type":"error"},{"inputs":[],"name":"InvalidOwnershipAcceptance","type":"error"},{"inputs":[],"name":"NotOwnerOrTimelock","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"OwnerCannotBeZero","type":"error"},{"inputs":[],"name":"SenderNotAuthorizedClaimer","type":"error"},{"inputs":[],"name":"SenderNotRewarder","type":"error"},{"inputs":[],"name":"TransferHelperTransferFailed","type":"error"},{"inputs":[],"name":"YieldCollectionPaused","type":"error"},{"inputs":[],"name":"YieldPeriodMustCompleteBeforeChangingToNewPeriod","type":"error"},{"anonymous":false,"inputs":[],"name":"DefaultInitialization","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RecoveredERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yieldRate","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"timelock_address","type":"address"}],"name":"TimelockChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"yield","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"YieldCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"YieldDurationUpdated","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_accounts","type":"address[]"}],"name":"bulkCheckpointOtherUsers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"checkpointOtherUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"_earned","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"eligibleCurrentVeFXS","outputs":[{"internalType":"uint256","name":"_eligibleVefxsBal","type":"uint256"},{"internalType":"uint256","name":"_storedEndingTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emittedToken","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emittedTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fractionParticipating","outputs":[{"internalType":"uint256","name":"_fraction","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getYield","outputs":[{"internalType":"uint256","name":"_yield0","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getYieldForDuration","outputs":[{"internalType":"uint256","name":"_yield","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"getYieldThirdParty","outputs":[{"internalType":"uint256","name":"_yield0","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"greylist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"greylistAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_timelockAddress","type":"address"},{"internalType":"address","name":"_emittedToken","type":"address"},{"internalType":"address","name":"_veFXSAggregator","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastTimeYieldApplicable","outputs":[{"internalType":"uint256","name":"_ts","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardNotifiers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_yieldCollectionPaused","type":"bool"}],"name":"setPauses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"address","name":"_claimer","type":"address"}],"name":"setThirdPartyClaimer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newTimelock","type":"address"}],"name":"setTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_veFXSAggregator","type":"address"}],"name":"setVeFXSAggregator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_yieldDuration","type":"uint256"}],"name":"setYieldDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRate","type":"uint256"},{"internalType":"bool","name":"_syncToo","type":"bool"}],"name":"setYieldRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"thirdPartyClaimers","outputs":[{"internalType":"address","name":"claimer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_notifierAddr","type":"address"}],"name":"toggleRewardNotifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalComboVeFXSSupplyStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalVeFXSParticipating","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userIsInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userVeFXSCheckpointed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userVeFXSEndpointCheckpointed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userYieldPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"veFXSAggregator","outputs":[{"internalType":"contract VeFXSAggregator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yieldCollectionPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yieldDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yieldPerVeFXS","outputs":[{"internalType":"uint256","name":"_yield","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yieldPerVeFXSStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yieldRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"yields","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60806040526017805460ff191690553480156018575f80fd5b505f80546001600160a01b0319163390811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160016002556017805461ff001916610100179055612826806100875f395ff3fe608060405234801561000f575f80fd5b5060043610610303575f3560e01c80638980f11f1161019d578063c2c4c5c1116100e8578063ebe2b12b11610093578063f8c8765e1161006e578063f8c8765e146106e8578063fc939bb1146106fb578063fff6cae914610703575f80fd5b8063ebe2b12b146106ac578063f3b0fb45146106b5578063f43ae1c7146106c8575f80fd5b8063dbdedb89116100c3578063dbdedb8914610663578063e172cf2114610683578063e9218ff61461068c575f80fd5b8063c2c4c5c114610630578063c8f33c9114610638578063d15166ff14610641575f80fd5b80639f8a835a11610148578063ad1148cb11610123578063ad1148cb146105db578063b1dd0ce9146105e8578063bdacb3031461061d575f80fd5b80639f8a835a146105a05780639faf3c6b146105b3578063a875f472146105bc575f80fd5b806391519bda1161017857806391519bda14610567578063941d9f651461057a578063948e25a21461058d575f80fd5b80638980f11f146105225780638c329f66146105355780638da5cb5b14610548575f80fd5b806350fe98ac1161025d5780636999ac931161020857806379ba5097116101e357806379ba5097146105095780637c26287114610511578063819abfcd14610519575f80fd5b80636999ac93146104c557806373f22f74146104ce57806374ea0b98146104f6575f80fd5b806356d9fff31161023857806356d9fff314610496578063681b5ffa1461049e5780636869f42f146104bd575f80fd5b806350fe98ac1461044e57806353a47bb71461046d57806354e04d151461048d575f80fd5b806331ca208c116102bd57806345ff83cb1161029857806345ff83cb146103d75780634bc66f32146103f65780634c5de8231461043b575f80fd5b806331ca208c1461038f5780633c6b16ab146103b157806342c92f6e146103c4575f80fd5b80631627540c116102ed5780631627540c1461035f57806319aec6d2146103745780632827962d1461037c575f80fd5b80628cc2621461030757806314b305371461032d575b5f80fd5b61031a6103153660046122cb565b61070b565b6040519081526020015b60405180910390f35b61034f61033b3660046122cb565b60116020525f908152604090205460ff1681565b6040519015158152602001610324565b61037261036d3660046122cb565b610904565b005b61031a6109ce565b61037261038a3660046122cb565b6109e4565b61034f61039d3660046122cb565b60156020525f908152604090205460ff1681565b6103726103bf3660046122e6565b610aa1565b6103726103d23660046122cb565b610c58565b61031a6103e53660046122cb565b60126020525f908152604090205481565b6006546104169073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610324565b6103726104493660046123c5565b610d21565b61031a61045c3660046122cb565b600e6020525f908152604090205481565b6001546104169073ffffffffffffffffffffffffffffffffffffffff1681565b61031a600c5481565b61031a610d63565b61031a6104ac3660046122cb565b60136020525f908152604090205481565b61031a610d79565b61031a60095481565b6104e16104dc3660046122cb565b610dd8565b60408051928352602083019190915201610324565b6103726105043660046122e6565b610eb2565b610372610fa7565b61031a61109a565b61031a600f5481565b610372610530366004612464565b6110a5565b61037261054336600461248e565b611192565b5f546104169073ffffffffffffffffffffffffffffffffffffffff1681565b6103726105753660046124d2565b61125a565b6103726105883660046122cb565b6112e3565b61037261059b3660046124f5565b6113ac565b6103726105ae3660046122cb565b611453565b61031a60105481565b61031a6105ca3660046122cb565b600d6020525f908152604090205481565b60175461034f9060ff1681565b6104166105f63660046122cb565b60166020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61037261062b3660046122cb565b611461565b61037261154a565b61031a60085481565b61034f61064f3660046122cb565b600b6020525f908152604090205460ff1681565b6003546104169073ffffffffffffffffffffffffffffffffffffffff1681565b61031a600a5481565b6004546104169073ffffffffffffffffffffffffffffffffffffffff1681565b61031a60075481565b61031a6106c33660046122cb565b611557565b6005546104169073ffffffffffffffffffffffffffffffffffffffff1681565b6103726106f6366004612510565b6115c8565b61031a611737565b610372611764565b73ffffffffffffffffffffffffffffffffffffffff81165f9081526011602052604081205460ff1661073e57505f919050565b5f8061074984610dd8565b9092509050620f42405f8390036108105773ffffffffffffffffffffffffffffffffffffffff85165f90815260146020526040902054821161078f57505f949350505050565b73ffffffffffffffffffffffffffffffffffffffff85165f908152601460205260408120546107be9084612596565b73ffffffffffffffffffffffffffffffffffffffff87165f90815260146020526040812054919250906107f19042612596565b90508061080183620f42406125a9565b61080b91906125c0565b925050505b73ffffffffffffffffffffffffffffffffffffffff85165f90815260126020526040812054808511156108455780915061085e565b600261085182876125f8565b61085b91906125c0565b91505b73ffffffffffffffffffffffffffffffffffffffff87165f908152600e6020526040902054610898620f4240670de0b6b3a76400006125a9565b73ffffffffffffffffffffffffffffffffffffffff89165f908152600d602052604090205485906108c7610d79565b6108d19190612596565b6108db90866125a9565b6108e591906125a9565b6108ef91906125c0565b6108f991906125f8565b979650505050505050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610954576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906020015b60405180910390a150565b5f600a546009546109df91906125a9565b905090565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590610a23575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15610a5a576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b335f908152600b602052604090205460ff16610ae9576040517fae582d4300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454610b0e9073ffffffffffffffffffffffffffffffffffffffff16333084611811565b610b16611764565b6007544210610b3457600a54610b2c90826125c0565b600955610b74565b5f42600754610b439190612596565b90505f60095482610b5491906125a9565b600a54909150610b6482856125f8565b610b6e91906125c0565b60095550505b426008819055600a54610b86916125f8565b600755600354604080517ff0657ab6000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163f0657ab6916004808201926020929091908290030181865afa158015610bf7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c1b919061260b565b6010556009546040805183815260208101929092527f6c07ee05dcf262f13abf9d87b846ee789d2f90fe991d495acd7d7fc109ee1f5591016109c3565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590610c97575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15610cce576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff165f908152600b6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b5f5b8151811015610d5f57610d34611764565b610d57828281518110610d4957610d49612622565b60200260200101515f6118ac565b600101610d23565b5050565b5f6007544210610d74575060075490565b504290565b5f6010545f03610d8a5750600c5490565b601054600954600854610d9b610d63565b610da59190612596565b610daf91906125a9565b610dc190670de0b6b3a76400006125a9565b610dcb91906125c0565b600c546109df91906125f8565b6003546040517fd96658d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301525f92839283929091169063d96658d990602401602060405180830381865afa158015610e4c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e70919061260b565b73ffffffffffffffffffffffffffffffffffffffff85165f9081526013602052604090205492509050428211610ea8575f9250610eac565b8092505b50915091565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590610ef1575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15610f28576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075415801590610f3b57506007544211155b15610f72576040517f350e95f600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a8190556040518181527fce653f06b9044b00e7d9d01b9b4228e84812092cb6a38371889bef19370d21f7906020016109c3565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ff8576040517fd74b334e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180545f80547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b5f6109df3333611c01565b5f5473ffffffffffffffffffffffffffffffffffffffff1633148015906110e4575060065473ffffffffffffffffffffffffffffffffffffffff163314155b1561111b576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5461113f90839073ffffffffffffffffffffffffffffffffffffffff1683611e0c565b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527f55350610fe57096d8c0ffa30beede987326bccfcb0b4415804164d0dd50ce8b1910160405180910390a15050565b5f5473ffffffffffffffffffffffffffffffffffffffff1633148015906111d1575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15611208576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260166020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590611299575060065473ffffffffffffffffffffffffffffffffffffffff163314155b156112d0576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60098290558015610d5f57610d5f611764565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590611322575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15611359576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff165f90815260156020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b5f5473ffffffffffffffffffffffffffffffffffffffff1633148015906113eb575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15611422576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b61145e8160016118ac565b50565b5f5473ffffffffffffffffffffffffffffffffffffffff1633148015906114a0575060065473ffffffffffffffffffffffffffffffffffffffff163314155b156114d7576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff02fdf7b40fb25784d39342249bbb15cee2bc0288f75ded1cf8ad2e63d4d91aa906020016109c3565b6115553360016118ac565b565b73ffffffffffffffffffffffffffffffffffffffff8181165f9081526016602052604081205490911633146115b8576040517f86e2586e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115c28233611c01565b92915050565b601754610100900460ff16806115f2575073ffffffffffffffffffffffffffffffffffffffff8216155b80611614575060055473ffffffffffffffffffffffffffffffffffffffff1615155b1561164b576040517fd08e7ac200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff9586167fffffffffffffffffffffffff000000000000000000000000000000000000000091821681178355600580549588169583168617905560048054831690951790945560068054958716958216959095179094556003805492909516919093161790925542600855908152600b6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905562093a80600a55601780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b5f6010545f0361174657505f90565b601054620f4240600f5461175a91906125a9565b6109df91906125c0565b61176c610d79565b600c55600354604080517ff0657ab6000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163f0657ab6916004808201926020929091908290030181865afa1580156117dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611801919061260b565b60105561180c610d63565b600855565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526118a6908590611f4c565b50505050565b80156118ba576118ba611764565b6118c38261205c565b73ffffffffffffffffffffffffffffffffffffffff8281165f818152601260205260408082205460035491517fd96658d9000000000000000000000000000000000000000000000000000000008152600481019490945293919291169063d96658d990602401602060405180830381865afa158015611944573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611968919061260b565b73ffffffffffffffffffffffffffffffffffffffff8581165f8181526012602052604080822085905560035490517f7eb1554e0000000000000000000000000000000000000000000000000000000081526004810193909352602483018290529394509290911690637eb1554e906044015f60405180830381865afa1580156119f3573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a389190810190612673565b90505f8082511115611a6557815f81518110611a5657611a56612622565b60200260200101516060015190505b600182511115611aee575f5b8251811015611aec57816fffffffffffffffffffffffffffffffff16838281518110611a9f57611a9f612622565b6020026020010151606001516fffffffffffffffffffffffffffffffff161015611ae457828181518110611ad557611ad5612622565b60200260200101516060015191505b600101611a71565b505b73ffffffffffffffffffffffffffffffffffffffff86165f9081526013602052604090206fffffffffffffffffffffffffffffffff82169055838310611b52575f611b398585612596565b905080600f54611b4991906125f8565b600f5550611b72565b5f611b5d8486612596565b905080600f54611b6d9190612596565b600f55505b73ffffffffffffffffffffffffffffffffffffffff86165f9081526011602052604090205460ff16611bf95773ffffffffffffffffffffffffffffffffffffffff86165f90815260116020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055601490915290204290555b505050505050565b5f6002805403611c72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002805560175460ff1615611cb3576040517f6efa33c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82611cbf8160016118ac565b73ffffffffffffffffffffffffffffffffffffffff84165f9081526015602052604090205460ff1615611d1e576040517f70e5228400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84165f908152600e602052604090205491508115611dda5773ffffffffffffffffffffffffffffffffffffffff8085165f908152600e6020526040812055600554611d8091168484611e0c565b6005546040805184815273ffffffffffffffffffffffffffffffffffffffff9283166020820152858316928716917fca927b8152f4c35113c332dd69d3f2fc3328428c7d560f0e84a556a3a4ef20a0910160405180910390a35b5073ffffffffffffffffffffffffffffffffffffffff9092165f90815260146020526040902042905550600160025590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291515f92839290871691611ea2919061276c565b5f604051808303815f865af19150503d805f8114611edb576040519150601f19603f3d011682016040523d82523d5f602084013e611ee0565b606091505b5091509150811580611f0e5750805115801590611f0e575080806020019051810190611f0c9190612782565b155b15611f45576040517f19a9708500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b5f611fad826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120bd9092919063ffffffff16565b8051909150156120575780806020019051810190611fcb9190612782565b612057576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611c69565b505050565b73ffffffffffffffffffffffffffffffffffffffff81161561145e575f6120828261070b565b73ffffffffffffffffffffffffffffffffffffffff83165f908152600e6020908152604080832093909355600c54600d909152919020555050565b60606120cb84845f856120d5565b90505b9392505050565b606082471015612167576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611c69565b73ffffffffffffffffffffffffffffffffffffffff85163b6121e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611c69565b5f808673ffffffffffffffffffffffffffffffffffffffff16858760405161220d919061276c565b5f6040518083038185875af1925050503d805f8114612247576040519150601f19603f3d011682016040523d82523d5f602084013e61224c565b606091505b50915091506108f9828286606083156122665750816120ce565b8251156122765782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c69919061279d565b73ffffffffffffffffffffffffffffffffffffffff8116811461145e575f80fd5b5f602082840312156122db575f80fd5b81356120ce816122aa565b5f602082840312156122f6575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160c0810167ffffffffffffffff8111828210171561234d5761234d6122fd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561239a5761239a6122fd565b604052919050565b5f67ffffffffffffffff8211156123bb576123bb6122fd565b5060051b60200190565b5f602082840312156123d5575f80fd5b813567ffffffffffffffff8111156123eb575f80fd5b8201601f810184136123fb575f80fd5b803561240e612409826123a2565b612353565b8082825260208201915060208360051b85010192508683111561242f575f80fd5b6020840193505b8284101561245a578335612449816122aa565b825260209384019390910190612436565b9695505050505050565b5f8060408385031215612475575f80fd5b8235612480816122aa565b946020939093013593505050565b5f806040838503121561249f575f80fd5b82356124aa816122aa565b915060208301356124ba816122aa565b809150509250929050565b801515811461145e575f80fd5b5f80604083850312156124e3575f80fd5b8235915060208301356124ba816124c5565b5f60208284031215612505575f80fd5b81356120ce816124c5565b5f805f8060808587031215612523575f80fd5b843561252e816122aa565b9350602085013561253e816122aa565b9250604085013561254e816122aa565b9150606085013561255e816122aa565b939692955090935050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156115c2576115c2612569565b80820281158282048414176115c2576115c2612569565b5f826125f3577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b808201808211156115c2576115c2612569565b5f6020828403121561261b575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b80516fffffffffffffffffffffffffffffffff8116811461266e575f80fd5b919050565b5f60208284031215612683575f80fd5b815167ffffffffffffffff811115612699575f80fd5b8201601f810184136126a9575f80fd5b80516126b7612409826123a2565b80828252602082019150602060c084028501019250868311156126d8575f80fd5b6020840193505b8284101561245a5760c084880312156126f6575f80fd5b6126fe61232a565b8451815261270e6020860161264f565b6020820152604085015180600f0b8114612726575f80fd5b60408201526127376060860161264f565b6060820152608085015161274a816122aa565b608082015260a08581015190820152825260c0909301926020909101906126df565b5f82518060208501845e5f920191825250919050565b5f60208284031215612792575f80fd5b81516120ce816124c5565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea2646970667358221220565a8ae0270c5492c7ab9a062f5e6be918bafe3fd432d31bf4d7e92ce14bda7164736f6c634300081a0033
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610303575f3560e01c80638980f11f1161019d578063c2c4c5c1116100e8578063ebe2b12b11610093578063f8c8765e1161006e578063f8c8765e146106e8578063fc939bb1146106fb578063fff6cae914610703575f80fd5b8063ebe2b12b146106ac578063f3b0fb45146106b5578063f43ae1c7146106c8575f80fd5b8063dbdedb89116100c3578063dbdedb8914610663578063e172cf2114610683578063e9218ff61461068c575f80fd5b8063c2c4c5c114610630578063c8f33c9114610638578063d15166ff14610641575f80fd5b80639f8a835a11610148578063ad1148cb11610123578063ad1148cb146105db578063b1dd0ce9146105e8578063bdacb3031461061d575f80fd5b80639f8a835a146105a05780639faf3c6b146105b3578063a875f472146105bc575f80fd5b806391519bda1161017857806391519bda14610567578063941d9f651461057a578063948e25a21461058d575f80fd5b80638980f11f146105225780638c329f66146105355780638da5cb5b14610548575f80fd5b806350fe98ac1161025d5780636999ac931161020857806379ba5097116101e357806379ba5097146105095780637c26287114610511578063819abfcd14610519575f80fd5b80636999ac93146104c557806373f22f74146104ce57806374ea0b98146104f6575f80fd5b806356d9fff31161023857806356d9fff314610496578063681b5ffa1461049e5780636869f42f146104bd575f80fd5b806350fe98ac1461044e57806353a47bb71461046d57806354e04d151461048d575f80fd5b806331ca208c116102bd57806345ff83cb1161029857806345ff83cb146103d75780634bc66f32146103f65780634c5de8231461043b575f80fd5b806331ca208c1461038f5780633c6b16ab146103b157806342c92f6e146103c4575f80fd5b80631627540c116102ed5780631627540c1461035f57806319aec6d2146103745780632827962d1461037c575f80fd5b80628cc2621461030757806314b305371461032d575b5f80fd5b61031a6103153660046122cb565b61070b565b6040519081526020015b60405180910390f35b61034f61033b3660046122cb565b60116020525f908152604090205460ff1681565b6040519015158152602001610324565b61037261036d3660046122cb565b610904565b005b61031a6109ce565b61037261038a3660046122cb565b6109e4565b61034f61039d3660046122cb565b60156020525f908152604090205460ff1681565b6103726103bf3660046122e6565b610aa1565b6103726103d23660046122cb565b610c58565b61031a6103e53660046122cb565b60126020525f908152604090205481565b6006546104169073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610324565b6103726104493660046123c5565b610d21565b61031a61045c3660046122cb565b600e6020525f908152604090205481565b6001546104169073ffffffffffffffffffffffffffffffffffffffff1681565b61031a600c5481565b61031a610d63565b61031a6104ac3660046122cb565b60136020525f908152604090205481565b61031a610d79565b61031a60095481565b6104e16104dc3660046122cb565b610dd8565b60408051928352602083019190915201610324565b6103726105043660046122e6565b610eb2565b610372610fa7565b61031a61109a565b61031a600f5481565b610372610530366004612464565b6110a5565b61037261054336600461248e565b611192565b5f546104169073ffffffffffffffffffffffffffffffffffffffff1681565b6103726105753660046124d2565b61125a565b6103726105883660046122cb565b6112e3565b61037261059b3660046124f5565b6113ac565b6103726105ae3660046122cb565b611453565b61031a60105481565b61031a6105ca3660046122cb565b600d6020525f908152604090205481565b60175461034f9060ff1681565b6104166105f63660046122cb565b60166020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61037261062b3660046122cb565b611461565b61037261154a565b61031a60085481565b61034f61064f3660046122cb565b600b6020525f908152604090205460ff1681565b6003546104169073ffffffffffffffffffffffffffffffffffffffff1681565b61031a600a5481565b6004546104169073ffffffffffffffffffffffffffffffffffffffff1681565b61031a60075481565b61031a6106c33660046122cb565b611557565b6005546104169073ffffffffffffffffffffffffffffffffffffffff1681565b6103726106f6366004612510565b6115c8565b61031a611737565b610372611764565b73ffffffffffffffffffffffffffffffffffffffff81165f9081526011602052604081205460ff1661073e57505f919050565b5f8061074984610dd8565b9092509050620f42405f8390036108105773ffffffffffffffffffffffffffffffffffffffff85165f90815260146020526040902054821161078f57505f949350505050565b73ffffffffffffffffffffffffffffffffffffffff85165f908152601460205260408120546107be9084612596565b73ffffffffffffffffffffffffffffffffffffffff87165f90815260146020526040812054919250906107f19042612596565b90508061080183620f42406125a9565b61080b91906125c0565b925050505b73ffffffffffffffffffffffffffffffffffffffff85165f90815260126020526040812054808511156108455780915061085e565b600261085182876125f8565b61085b91906125c0565b91505b73ffffffffffffffffffffffffffffffffffffffff87165f908152600e6020526040902054610898620f4240670de0b6b3a76400006125a9565b73ffffffffffffffffffffffffffffffffffffffff89165f908152600d602052604090205485906108c7610d79565b6108d19190612596565b6108db90866125a9565b6108e591906125a9565b6108ef91906125c0565b6108f991906125f8565b979650505050505050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610954576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906020015b60405180910390a150565b5f600a546009546109df91906125a9565b905090565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590610a23575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15610a5a576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b335f908152600b602052604090205460ff16610ae9576040517fae582d4300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454610b0e9073ffffffffffffffffffffffffffffffffffffffff16333084611811565b610b16611764565b6007544210610b3457600a54610b2c90826125c0565b600955610b74565b5f42600754610b439190612596565b90505f60095482610b5491906125a9565b600a54909150610b6482856125f8565b610b6e91906125c0565b60095550505b426008819055600a54610b86916125f8565b600755600354604080517ff0657ab6000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163f0657ab6916004808201926020929091908290030181865afa158015610bf7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c1b919061260b565b6010556009546040805183815260208101929092527f6c07ee05dcf262f13abf9d87b846ee789d2f90fe991d495acd7d7fc109ee1f5591016109c3565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590610c97575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15610cce576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff165f908152600b6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b5f5b8151811015610d5f57610d34611764565b610d57828281518110610d4957610d49612622565b60200260200101515f6118ac565b600101610d23565b5050565b5f6007544210610d74575060075490565b504290565b5f6010545f03610d8a5750600c5490565b601054600954600854610d9b610d63565b610da59190612596565b610daf91906125a9565b610dc190670de0b6b3a76400006125a9565b610dcb91906125c0565b600c546109df91906125f8565b6003546040517fd96658d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301525f92839283929091169063d96658d990602401602060405180830381865afa158015610e4c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e70919061260b565b73ffffffffffffffffffffffffffffffffffffffff85165f9081526013602052604090205492509050428211610ea8575f9250610eac565b8092505b50915091565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590610ef1575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15610f28576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075415801590610f3b57506007544211155b15610f72576040517f350e95f600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a8190556040518181527fce653f06b9044b00e7d9d01b9b4228e84812092cb6a38371889bef19370d21f7906020016109c3565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ff8576040517fd74b334e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180545f80547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b5f6109df3333611c01565b5f5473ffffffffffffffffffffffffffffffffffffffff1633148015906110e4575060065473ffffffffffffffffffffffffffffffffffffffff163314155b1561111b576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5461113f90839073ffffffffffffffffffffffffffffffffffffffff1683611e0c565b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527f55350610fe57096d8c0ffa30beede987326bccfcb0b4415804164d0dd50ce8b1910160405180910390a15050565b5f5473ffffffffffffffffffffffffffffffffffffffff1633148015906111d1575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15611208576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260166020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590611299575060065473ffffffffffffffffffffffffffffffffffffffff163314155b156112d0576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60098290558015610d5f57610d5f611764565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590611322575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15611359576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff165f90815260156020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b5f5473ffffffffffffffffffffffffffffffffffffffff1633148015906113eb575060065473ffffffffffffffffffffffffffffffffffffffff163314155b15611422576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b61145e8160016118ac565b50565b5f5473ffffffffffffffffffffffffffffffffffffffff1633148015906114a0575060065473ffffffffffffffffffffffffffffffffffffffff163314155b156114d7576040517ffee4291a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff02fdf7b40fb25784d39342249bbb15cee2bc0288f75ded1cf8ad2e63d4d91aa906020016109c3565b6115553360016118ac565b565b73ffffffffffffffffffffffffffffffffffffffff8181165f9081526016602052604081205490911633146115b8576040517f86e2586e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115c28233611c01565b92915050565b601754610100900460ff16806115f2575073ffffffffffffffffffffffffffffffffffffffff8216155b80611614575060055473ffffffffffffffffffffffffffffffffffffffff1615155b1561164b576040517fd08e7ac200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff9586167fffffffffffffffffffffffff000000000000000000000000000000000000000091821681178355600580549588169583168617905560048054831690951790945560068054958716958216959095179094556003805492909516919093161790925542600855908152600b6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905562093a80600a55601780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b5f6010545f0361174657505f90565b601054620f4240600f5461175a91906125a9565b6109df91906125c0565b61176c610d79565b600c55600354604080517ff0657ab6000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163f0657ab6916004808201926020929091908290030181865afa1580156117dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611801919061260b565b60105561180c610d63565b600855565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526118a6908590611f4c565b50505050565b80156118ba576118ba611764565b6118c38261205c565b73ffffffffffffffffffffffffffffffffffffffff8281165f818152601260205260408082205460035491517fd96658d9000000000000000000000000000000000000000000000000000000008152600481019490945293919291169063d96658d990602401602060405180830381865afa158015611944573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611968919061260b565b73ffffffffffffffffffffffffffffffffffffffff8581165f8181526012602052604080822085905560035490517f7eb1554e0000000000000000000000000000000000000000000000000000000081526004810193909352602483018290529394509290911690637eb1554e906044015f60405180830381865afa1580156119f3573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a389190810190612673565b90505f8082511115611a6557815f81518110611a5657611a56612622565b60200260200101516060015190505b600182511115611aee575f5b8251811015611aec57816fffffffffffffffffffffffffffffffff16838281518110611a9f57611a9f612622565b6020026020010151606001516fffffffffffffffffffffffffffffffff161015611ae457828181518110611ad557611ad5612622565b60200260200101516060015191505b600101611a71565b505b73ffffffffffffffffffffffffffffffffffffffff86165f9081526013602052604090206fffffffffffffffffffffffffffffffff82169055838310611b52575f611b398585612596565b905080600f54611b4991906125f8565b600f5550611b72565b5f611b5d8486612596565b905080600f54611b6d9190612596565b600f55505b73ffffffffffffffffffffffffffffffffffffffff86165f9081526011602052604090205460ff16611bf95773ffffffffffffffffffffffffffffffffffffffff86165f90815260116020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055601490915290204290555b505050505050565b5f6002805403611c72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002805560175460ff1615611cb3576040517f6efa33c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82611cbf8160016118ac565b73ffffffffffffffffffffffffffffffffffffffff84165f9081526015602052604090205460ff1615611d1e576040517f70e5228400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84165f908152600e602052604090205491508115611dda5773ffffffffffffffffffffffffffffffffffffffff8085165f908152600e6020526040812055600554611d8091168484611e0c565b6005546040805184815273ffffffffffffffffffffffffffffffffffffffff9283166020820152858316928716917fca927b8152f4c35113c332dd69d3f2fc3328428c7d560f0e84a556a3a4ef20a0910160405180910390a35b5073ffffffffffffffffffffffffffffffffffffffff9092165f90815260146020526040902042905550600160025590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291515f92839290871691611ea2919061276c565b5f604051808303815f865af19150503d805f8114611edb576040519150601f19603f3d011682016040523d82523d5f602084013e611ee0565b606091505b5091509150811580611f0e5750805115801590611f0e575080806020019051810190611f0c9190612782565b155b15611f45576040517f19a9708500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b5f611fad826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120bd9092919063ffffffff16565b8051909150156120575780806020019051810190611fcb9190612782565b612057576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611c69565b505050565b73ffffffffffffffffffffffffffffffffffffffff81161561145e575f6120828261070b565b73ffffffffffffffffffffffffffffffffffffffff83165f908152600e6020908152604080832093909355600c54600d909152919020555050565b60606120cb84845f856120d5565b90505b9392505050565b606082471015612167576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611c69565b73ffffffffffffffffffffffffffffffffffffffff85163b6121e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611c69565b5f808673ffffffffffffffffffffffffffffffffffffffff16858760405161220d919061276c565b5f6040518083038185875af1925050503d805f8114612247576040519150601f19603f3d011682016040523d82523d5f602084013e61224c565b606091505b50915091506108f9828286606083156122665750816120ce565b8251156122765782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c69919061279d565b73ffffffffffffffffffffffffffffffffffffffff8116811461145e575f80fd5b5f602082840312156122db575f80fd5b81356120ce816122aa565b5f602082840312156122f6575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160c0810167ffffffffffffffff8111828210171561234d5761234d6122fd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561239a5761239a6122fd565b604052919050565b5f67ffffffffffffffff8211156123bb576123bb6122fd565b5060051b60200190565b5f602082840312156123d5575f80fd5b813567ffffffffffffffff8111156123eb575f80fd5b8201601f810184136123fb575f80fd5b803561240e612409826123a2565b612353565b8082825260208201915060208360051b85010192508683111561242f575f80fd5b6020840193505b8284101561245a578335612449816122aa565b825260209384019390910190612436565b9695505050505050565b5f8060408385031215612475575f80fd5b8235612480816122aa565b946020939093013593505050565b5f806040838503121561249f575f80fd5b82356124aa816122aa565b915060208301356124ba816122aa565b809150509250929050565b801515811461145e575f80fd5b5f80604083850312156124e3575f80fd5b8235915060208301356124ba816124c5565b5f60208284031215612505575f80fd5b81356120ce816124c5565b5f805f8060808587031215612523575f80fd5b843561252e816122aa565b9350602085013561253e816122aa565b9250604085013561254e816122aa565b9150606085013561255e816122aa565b939692955090935050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156115c2576115c2612569565b80820281158282048414176115c2576115c2612569565b5f826125f3577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b808201808211156115c2576115c2612569565b5f6020828403121561261b575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b80516fffffffffffffffffffffffffffffffff8116811461266e575f80fd5b919050565b5f60208284031215612683575f80fd5b815167ffffffffffffffff811115612699575f80fd5b8201601f810184136126a9575f80fd5b80516126b7612409826123a2565b80828252602082019150602060c084028501019250868311156126d8575f80fd5b6020840193505b8284101561245a5760c084880312156126f6575f80fd5b6126fe61232a565b8451815261270e6020860161264f565b6020820152604085015180600f0b8114612726575f80fd5b60408201526127376060860161264f565b6060820152608085015161274a816122aa565b608082015260a08581015190820152825260c0909301926020909101906126df565b5f82518060208501845e5f920191825250919050565b5f60208284031215612792575f80fd5b81516120ce816124c5565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea2646970667358221220565a8ae0270c5492c7ab9a062f5e6be918bafe3fd432d31bf4d7e92ce14bda7164736f6c634300081a0033
Deployed Bytecode Sourcemap
190207:31982:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;198625:3352;;;;;;:::i;:::-;;:::i;:::-;;;571:25:1;;;559:2;544:18;198625:3352:0;;;;;;;;192460:49;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;772:14:1;;765:22;747:41;;735:2;720:18;192460:49:0;607:187:1;101035:141:0;;;;;;:::i;:::-;;:::i;:::-;;202103:123;;;:::i;212774:146::-;;;;;;:::i;:::-;;:::i;193130:40::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;209685:1175;;;;;;:::i;:::-;;:::i;212484:158::-;;;;;;:::i;:::-;;:::i;192574:56::-;;;;;;:::i;:::-;;;;;;;;;;;;;;190994:30;;;;;;;;;;;;1206:42:1;1194:55;;;1176:74;;1164:2;1149:18;190994:30:0;1030:226:1;206506:421:0;;;;;;:::i;:::-;;:::i;192069:41::-;;;;;;:::i;:::-;;;;;;;;;;;;;;100886:29;;;;;;;;;191785:34;;;;;;197871:160;;;:::i;192806:64::-;;;;;;:::i;:::-;;;;;;;;;;;;;;198126:349;;;:::i;191378:24::-;;;;;;197154:624;;;;;;:::i;:::-;;:::i;:::-;;;;3375:25:1;;;3431:2;3416:18;;3409:34;;;;3348:18;197154:624:0;3201:248:1;211719:324:0;;;;;;:::i;:::-;;:::i;101184:354::-;;;:::i;207990:165::-;;;:::i;192252:38::-;;;;;;211303:306;;;;;;:::i;:::-;;:::i;213871:144::-;;;;;;:::i;:::-;;:::i;100859:20::-;;;;;;;;;213373:175;;;;;;:::i;:::-;;:::i;212225:126::-;;;;;;:::i;:::-;;:::i;213032:135::-;;;;;;:::i;:::-;;:::i;206297:106::-;;;;;;:::i;:::-;;:::i;192357:42::-;;;;;;191897:56;;;;;;:::i;:::-;;;;;;;;;;;;;;193649:41;;;;;;;;;193521:68;;;;;;:::i;:::-;;;;;;;;;;;;;;;;214122:161;;;;;;:::i;:::-;;:::i;206972:83::-;;;:::i;191277:29::-;;;;;;191603:47;;;;;;:::i;:::-;;;;;;;;;;;;;;;;190666:38;;;;;;;;;191463:28;;;;;;190772:25;;;;;;;;;191155:27;;;;;;208568:365;;;;;;:::i;:::-;;:::i;190910:34::-;;;;;;;;;195332:981;;;;;;:::i;:::-;;:::i;196629:236::-;;;:::i;208987:576::-;;;:::i;198625:3352::-;198862:27;;;198680:15;198862:27;;;:17;:27;;;;;;;;198857:42;;-1:-1:-1;198898:1:0;;198625:3352;-1:-1:-1;198625:3352:0:o;198857:42::-;198953:28;198983:23;199010:30;199031:8;199010:20;:30::i;:::-;198952:88;;-1:-1:-1;198952:88:0;-1:-1:-1;193320:3:0;199091:28;199226:25;;;199222:1228;;199563:29;;;;;;;:19;:29;;;;;;:48;-1:-1:-1;199559:880:0;;-1:-1:-1;199700:1:0;;198625:3352;-1:-1:-1;;;;198625:3352:0:o;199559:880::-;200014:29;;;199973:20;200014:29;;;:19;:29;;;;;;199996:47;;:15;:47;:::i;:::-;200166:29;;;200128:17;200166:29;;;:19;:29;;;;;;199973:70;;-1:-1:-1;200128:17:0;200148:47;;:15;:47;:::i;:::-;200128:67;-1:-1:-1;200128:67:0;200298:30;200316:12;193320:3;200298:30;:::i;:::-;200297:44;;;;:::i;:::-;200274:67;;199776:663;;199559:880;200649:31;;;200587:25;200649:31;;;:21;:31;;;;;;200829:38;;;200825:924;;;200954:15;200934:35;;200825:924;;;201211:1;201169:38;201192:15;201169:20;:38;:::i;:::-;201168:44;;;;:::i;:::-;201148:64;;200825:924;201952:16;;;;;;;:6;:16;;;;;;201913:22;193320:3;201913:4;:22;:::i;:::-;201840:31;;;;;;;:21;:31;;;;;;201875:20;;201822:15;:13;:15::i;:::-;:49;;;;:::i;:::-;201801:71;;:17;:71;:::i;:::-;:94;;;;:::i;:::-;201800:136;;;;:::i;:::-;:168;;;;:::i;:::-;201792:177;198625:3352;-1:-1:-1;;;;;;;198625:3352:0:o;101035:141::-;101689:5;;;;101675:10;:19;101671:43;;101703:11;;;;;;;;;;;;;;101671:43;101107:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;101146:22:::1;::::0;1176:74:1;;;101146:22:0::1;::::0;1164:2:1;1149:18;101146:22:0::1;;;;;;;;101035:141:::0;:::o;202103:123::-;202157:14;202204:13;;202192:9;;:25;;;;:::i;:::-;202184:34;;202103:123;:::o;212774:146::-;194315:5;;;;194301:10;:19;;;;:52;;-1:-1:-1;194338:15:0;;;;194324:10;:29;;194301:52;194297:85;;;194362:20;;;;;;;;;;;;;;194297:85;212861:15:::1;:51:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;212774:146::o;209685:1175::-;209829:10;209813:27;;;;:15;:27;;;;;;;;209808:60;;209849:19;;;;;;;;;;;;;;209808:60;210055:12;;:65;;:12;;210085:10;210105:4;210112:7;210055:29;:65::i;:::-;210175:6;:4;:6::i;:::-;210254:12;;210235:15;:31;210231:300;;210305:13;;210295:23;;:7;:23;:::i;:::-;210283:9;:35;210231:300;;;210351:17;210386:15;210371:12;;:30;;;;:::i;:::-;210351:50;;210416:16;210447:9;;210435;:21;;;;:::i;:::-;210506:13;;210416:40;;-1:-1:-1;210484:18:0;210416:40;210484:7;:18;:::i;:::-;210483:36;;;;:::i;:::-;210471:9;:48;-1:-1:-1;;210231:300:0;210601:15;210584:14;:32;;;210660:13;;210642:31;;;:::i;:::-;210627:12;:46;210758:15;;:45;;;;;;;;:15;;;;;:43;;:45;;;;;;;;;;;;;;;:15;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;210728:27;:75;210842:9;;210821:31;;;3375:25:1;;;3431:2;3416:18;;3409:34;;;;210821:31:0;;3348:18:1;210821:31:0;3201:248:1;212484:158:0;194315:5;;;;194301:10;:19;;;;:52;;-1:-1:-1;194338:15:0;;;;194324:10;:29;;194301:52;194297:85;;;194362:20;;;;;;;;;;;;;;194297:85;212604:30:::1;;;::::0;;;:15:::1;:30;::::0;;;;;;212570:64;;::::1;212604:30;::::0;;::::1;212603:31;212570:64;::::0;;212484:158::o;206506:421::-;206632:9;206627:293;206651:9;:16;206647:1;:20;206627:293;;;206724:6;:4;:6::i;:::-;206808:36;206824:9;206834:1;206824:12;;;;;;;;:::i;:::-;;;;;;;206838:5;206808:15;:36::i;:::-;206890:3;;206627:293;;;;206506:421;:::o;197871:160::-;197927:11;197977:12;;197959:15;:30;:63;;-1:-1:-1;198010:12:0;;;202103:123::o;197959:63::-;-1:-1:-1;197992:15:0;;197871:160::o;198126:349::-;198172:14;198203:27;;198234:1;198203:32;198199:269;;-1:-1:-1;198259:19:0;;;198126:349::o;198199:269::-;198427:27;;198407:9;;198389:14;;198361:25;:23;:25::i;:::-;:42;;;;:::i;:::-;198360:56;;;;:::i;:::-;:63;;198419:4;198360:63;:::i;:::-;198359:95;;;;:::i;:::-;198319:19;;:136;;;;:::i;197154:624::-;197388:15;;:39;;;;;:15;1194:55:1;;;197388:39:0;;;1176:74:1;197236:25:0;;;;;;197388:15;;;;:32;;1149:18:1;;197388:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;197509:36;;;;;;;:29;:36;;;;;;;-1:-1:-1;197364:63:0;-1:-1:-1;197614:15:0;:41;-1:-1:-1;197610:161:0;;197692:1;197672:21;;197610:161;;;197746:13;197726:33;;197610:161;197295:483;197154:624;;;:::o;211719:324::-;194315:5;;;;194301:10;:19;;;;:52;;-1:-1:-1;194338:15:0;;;;194324:10;:29;;194301:52;194297:85;;;194362:20;;;;;;;;;;;;;;194297:85;211806:12:::1;::::0;:17;;::::1;::::0;:52:::1;;;211846:12;;211827:15;:31;;211806:52;211802:142;;;211882:50;;;;;;;;;;;;;;211802:142;211954:13;:30:::0;;;212000:35:::1;::::0;571:25:1;;;212000:35:0::1;::::0;559:2:1;544:18;212000:35:0::1;425:177:1::0;101184:354:0;101357:14;;;;101343:10;:28;101339:69;;101380:28;;;;;;;;;;;;;;101339:69;101437:5;;;101444:14;101424:35;;;101437:5;;;;7634:74:1;;101444:14:0;;;;7739:2:1;7724:18;;7717:83;101424:35:0;;7607:18:1;101424:35:0;;;;;;;101478:14;;;;101470:22;;;;;;101478:14;;;101470:22;;;;101503:27;;;101184:354::o;207990:165::-;208028:15;208114:33;208124:10;208136;208114:9;:33::i;211303:306::-;194315:5;;;;194301:10;:19;;;;:52;;-1:-1:-1;194338:15:0;;;;194324:10;:29;;194301:52;194297:85;;;194362:20;;;;;;;;;;;;;;194297:85;211522:5:::1;::::0;211479:63:::1;::::0;211507:13;;211522:5:::1;;211529:12:::0;211479:27:::1;:63::i;:::-;211558:43;::::0;;8015:42:1;8003:55;;7985:74;;8090:2;8075:18;;8068:34;;;211558:43:0::1;::::0;7958:18:1;211558:43:0::1;;;;;;;211303:306:::0;;:::o;213871:144::-;194315:5;;;;194301:10;:19;;;;:52;;-1:-1:-1;194338:15:0;;;;194324:10;:29;;194301:52;194297:85;;;194362:20;;;;;;;;;;;;;;194297:85;213969:27:::1;::::0;;::::1;;::::0;;;:18:::1;:27;::::0;;;;:38;;;::::1;::::0;;;::::1;;::::0;;213871:144::o;213373:175::-;194315:5;;;;194301:10;:19;;;;:52;;-1:-1:-1;194338:15:0;;;;194324:10;:29;;194301:52;194297:85;;;194362:20;;;;;;;;;;;;;;194297:85;213461:9:::1;:20:::0;;;213494:47;::::1;;;213523:6;:4;:6::i;212225:126::-:0;194315:5;;;;194301:10;:19;;;;:52;;-1:-1:-1;194338:15:0;;;;194324:10;:29;;194301:52;194297:85;;;194362:20;;;;;;;;;;;;;;194297:85;212324:18:::1;;;::::0;;;:8:::1;:18;::::0;;;;;;212301:42;;::::1;212324:18;::::0;;::::1;212322:21;212301:42;::::0;;212225:126::o;213032:135::-;194315:5;;;;194301:10;:19;;;;:52;;-1:-1:-1;194338:15:0;;;;194324:10;:29;;194301:52;194297:85;;;194362:20;;;;;;;;;;;;;;194297:85;213113:21:::1;:46:::0;;;::::1;::::0;::::1;;::::0;;;::::1;::::0;;213032:135::o;206297:106::-;206364:31;206380:8;206390:4;206364:15;:31::i;:::-;206297:106;:::o;214122:161::-;194315:5;;;;194301:10;:19;;;;:52;;-1:-1:-1;194338:15:0;;;;194324:10;:29;;194301:52;194297:85;;;194362:20;;;;;;;;;;;;;;194297:85;214198:15:::1;:30:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;214246:29:::1;::::0;1176:74:1;;;214246:29:0::1;::::0;1164:2:1;1149:18;214246:29:0::1;1030:226:1::0;206972:83:0;207014:33;207030:10;207042:4;207014:15;:33::i;:::-;206972:83::o;208568:365::-;208727:41;:27;;;208631:15;208727:27;;;:18;:27;;;;;;208631:15;;208727:27;208758:10;208727:41;208723:82;;208777:28;;;;;;;;;;;;;;208723:82;208895:30;208905:7;208914:10;208895:9;:30::i;:::-;208885:40;208568:365;-1:-1:-1;;208568:365:0:o;195332:981::-;195601:14;;;;;;;;:45;;-1:-1:-1;195619:27:0;;;;195601:45;:82;;;-1:-1:-1;195650:19:0;;:33;:19;:33;;195601:82;195597:140;;;195707:18;;;;;;;;;;;;;;195597:140;195783:5;:14;;;;;;;;;;;;;;195841:19;:35;;;;;;;;;;;;195887:12;:35;;;;;;;;;;195933:15;:34;;;;;;;;;;;;;;;196017:15;:51;;;;;;;;;;;;;;196137:15;196120:14;:32;196163:23;;;:15;:23;;;;;:30;;;;195783:14;196163:30;;;196220:7;196204:13;:23;196284:14;:21;;;;195783:14;196284:21;;;195332:981::o;196629:236::-;196685:17;196719:27;;196750:1;196719:32;196715:142;;-1:-1:-1;196760:1:0;;196629:236::o;196715:142::-;196830:27;;193320:3;196785:23;;:41;;;;:::i;:::-;196784:73;;;;:::i;208987:576::-;209146:15;:13;:15::i;:::-;209124:19;:37;209314:15;;:45;;;;;;;;:15;;;;;:43;;:45;;;;;;;;;;;;;;;:15;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;209284:27;:75;209484:25;:23;:25::i;:::-;209467:14;:42;208987:576::o;137118:248::-;137289:68;;;8345:42:1;8333:55;;;137289:68:0;;;8315:74:1;8425:55;;8405:18;;;8398:83;8497:18;;;;8490:34;;;137289:68:0;;;;;;;;;;8288:18:1;;;;137289:68:0;;;;;;;;;;137312:27;137289:68;;;137262:96;;137282:5;;137262:19;:96::i;:::-;137118:248;;;;:::o;202781:3060::-;203086:8;203082:20;;;203096:6;:4;:6::i;:::-;203156:21;203168:8;203156:11;:21::i;:::-;203268:31;;;;203241:24;203268:31;;;:21;:31;;;;;;;203397:15;;:42;;;;;;;;1176:74:1;;;;203268:31:0;203241:24;;203397:15;;;:32;;1149:18:1;;203397:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;203503:31;;;;;;;;:21;:31;;;;;;:50;;;203664:15;;:91;;;;;;;;8703:74:1;;;;8793:18;;;8786:50;;;203503::0;;-1:-1:-1;203503:31:0;203664:15;;;;:37;;8676:18:1;;203664:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;203603:152;;204095:30;204232:1;204197:25;:32;:36;204193:192;;;204341:25;204367:1;204341:28;;;;;;;;:::i;:::-;;;;;;;:32;;;204316:57;;204193:192;204497:1;204462:25;:32;:36;204458:569;;;204586:9;204581:435;204601:25;:32;204597:1;:36;204581:435;;;204801:22;204766:57;;:25;204792:1;204766:28;;;;;;;;:::i;:::-;;;;;;;:32;;;:57;;;204762:163;;;204873:25;204899:1;204873:28;;;;;;;;:::i;:::-;;;;;;;:32;;;204848:57;;204762:163;204978:3;;204581:435;;;;204458:569;205129:39;;;;;;;:29;:39;;;;;:64;;;;;205260:36;;;205256:368;;205313:18;205334:35;205353:16;205334;:35;:::i;:::-;205313:56;;205436:10;205410:23;;:36;;;;:::i;:::-;205384:23;:62;-1:-1:-1;205256:368:0;;;205479:18;205500:35;205519:16;205500;:35;:::i;:::-;205479:56;;205602:10;205576:23;;:36;;;;:::i;:::-;205550:23;:62;-1:-1:-1;205256:368:0;205682:27;;;;;;;:17;:27;;;;;;;;205677:157;;205726:27;;;;;;;:17;:27;;;;;;;;:34;;;;205756:4;205726:34;;;205775:19;:29;;;;;205807:15;205775:47;;205677:157;202848:2993;;;;202781:3060;;:::o;207315:585::-;207476:15;73099:1;73697:7;;:19;73689:63;;;;;;;10960:2:1;73689:63:0;;;10942:21:1;10999:2;10979:18;;;10972:30;11038:33;11018:18;;;11011:61;11089:18;;73689:63:0;;;;;;;;;73099:1;73830:18;;194519:21:::1;::::0;::::1;;194515:57;;;194549:23;;;;;;;;;;;;;;194515:57;207458:7:::2;194689:30;194705:7;194714:4;194689:15;:30::i;:::-;207508:17:::3;::::0;::::3;;::::0;;;:8:::3;:17;::::0;;;;;::::3;;207504:49;;;207534:19;;;;;;;;;;;;;;207504:49;207576:15;::::0;::::3;;::::0;;;:6:::3;:15;::::0;;;;;;-1:-1:-1;207606:11:0;;207602:232:::3;;207634:15;::::0;;::::3;207652:1;207634:15:::0;;;:6:::3;:15;::::0;;;;:19;207696::::3;::::0;207668:69:::3;::::0;207696:19:::3;207717:10:::0;207729:7;207668:27:::3;:69::i;:::-;207802:19;::::0;207757:65:::3;::::0;;11292:25:1;;;207757:65:0::3;207802:19:::0;;::::3;11348:2:1::0;11333:18;;11326:83;207757:65:0;;::::3;::::0;;::::3;::::0;::::3;::::0;11265:18:1;207757:65:0::3;;;;;;;207602:232;-1:-1:-1::0;207846:28:0::3;::::0;;::::3;;::::0;;;:19:::3;:28;::::0;;;;207877:15:::3;207846:46:::0;;-1:-1:-1;73055:1:0;74009:7;:22;207315:585;:::o;93339:480::-;93537:45;;;93526:10;8003:55:1;;;93537:45:0;;;7985:74:1;8075:18;;;;8068:34;;;93537:45:0;;;;;;;;;;7958:18:1;;;;93537:45:0;;;;;;;;;;;;;93526:57;;-1:-1:-1;;;;93526:10:0;;;;:57;;93537:45;93526:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93490:93;;;;93714:7;93713:8;:59;;;-1:-1:-1;93726:11:0;;:16;;;;:45;;;93758:4;93747:24;;;;;;;;;;;;:::i;:::-;93746:25;93726:45;93709:102;;;93781:30;;;;;;;;;;;;;;93709:102;93412:407;;93339:480;;;:::o;139966:716::-;140390:23;140416:69;140444:4;140416:69;;;;;;;;;;;;;;;;;140424:5;140416:27;;;;:69;;;;;:::i;:::-;140500:17;;140390:95;;-1:-1:-1;140500:21:0;140496:179;;140597:10;140586:30;;;;;;;;;;;;:::i;:::-;140578:85;;;;;;;12178:2:1;140578:85:0;;;12160:21:1;12217:2;12197:18;;;12190:30;12256:34;12236:18;;;12229:62;12327:12;12307:18;;;12300:40;12357:19;;140578:85:0;11976:406:1;140578:85:0;140036:646;139966:716;;:::o;205931:264::-;205994:22;;;;205990:198;;206033:15;206051:16;206058:8;206051:6;:16::i;:::-;206082;;;;;;;:6;:16;;;;;;;;:26;;;;206157:19;;206123:21;:31;;;;;;:53;-1:-1:-1;205931:264:0;:::o;83202:229::-;83339:12;83371:52;83393:6;83401:4;83407:1;83410:12;83371:21;:52::i;:::-;83364:59;;83202:229;;;;;;:::o;84322:510::-;84492:12;84550:5;84525:21;:30;;84517:81;;;;;;;12589:2:1;84517:81:0;;;12571:21:1;12628:2;12608:18;;;12601:30;12667:34;12647:18;;;12640:62;12738:8;12718:18;;;12711:36;12764:19;;84517:81:0;12387:402:1;84517:81:0;80752:19;;;;84609:60;;;;;;;12996:2:1;84609:60:0;;;12978:21:1;13035:2;13015:18;;;13008:30;13074:31;13054:18;;;13047:59;13123:18;;84609:60:0;12794:353:1;84609:60:0;84683:12;84697:23;84724:6;:11;;84743:5;84750:4;84724:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84682:73;;;;84773:51;84790:7;84799:10;84811:12;87158;87187:7;87183:580;;;-1:-1:-1;87218:10:0;87211:17;;87183:580;87332:17;;:21;87328:424;;87580:10;87574:17;87641:15;87628:10;87624:2;87620:19;87613:44;87328:424;87723:12;87716:20;;;;;;;;;;;:::i;14:154:1:-;100:42;93:5;89:54;82:5;79:65;69:93;;158:1;155;148:12;173:247;232:6;285:2;273:9;264:7;260:23;256:32;253:52;;;301:1;298;291:12;253:52;340:9;327:23;359:31;384:5;359:31;:::i;799:226::-;858:6;911:2;899:9;890:7;886:23;882:32;879:52;;;927:1;924;917:12;879:52;-1:-1:-1;972:23:1;;799:226;-1:-1:-1;799:226:1:o;1261:184::-;1313:77;1310:1;1303:88;1410:4;1407:1;1400:15;1434:4;1431:1;1424:15;1450:253;1522:2;1516:9;1564:4;1552:17;;1599:18;1584:34;;1620:22;;;1581:62;1578:88;;;1646:18;;:::i;:::-;1682:2;1675:22;1450:253;:::o;1708:334::-;1779:2;1773:9;1835:2;1825:13;;1840:66;1821:86;1809:99;;1938:18;1923:34;;1959:22;;;1920:62;1917:88;;;1985:18;;:::i;:::-;2021:2;2014:22;1708:334;;-1:-1:-1;1708:334:1:o;2047:183::-;2107:4;2140:18;2132:6;2129:30;2126:56;;;2162:18;;:::i;:::-;-1:-1:-1;2207:1:1;2203:14;2219:4;2199:25;;2047:183::o;2235:961::-;2319:6;2372:2;2360:9;2351:7;2347:23;2343:32;2340:52;;;2388:1;2385;2378:12;2340:52;2428:9;2415:23;2461:18;2453:6;2450:30;2447:50;;;2493:1;2490;2483:12;2447:50;2516:22;;2569:4;2561:13;;2557:27;-1:-1:-1;2547:55:1;;2598:1;2595;2588:12;2547:55;2638:2;2625:16;2661:64;2677:47;2717:6;2677:47;:::i;:::-;2661:64;:::i;:::-;2747:3;2771:6;2766:3;2759:19;2803:2;2798:3;2794:12;2787:19;;2858:2;2848:6;2845:1;2841:14;2837:2;2833:23;2829:32;2815:46;;2884:7;2876:6;2873:19;2870:39;;;2905:1;2902;2895:12;2870:39;2937:2;2933;2929:11;2918:22;;2949:217;2965:6;2960:3;2957:15;2949:217;;;3045:3;3032:17;3062:31;3087:5;3062:31;:::i;:::-;3106:18;;3153:2;2982:12;;;;3144;;;;2949:217;;;3185:5;2235:961;-1:-1:-1;;;;;;2235:961:1:o;3454:367::-;3522:6;3530;3583:2;3571:9;3562:7;3558:23;3554:32;3551:52;;;3599:1;3596;3589:12;3551:52;3638:9;3625:23;3657:31;3682:5;3657:31;:::i;:::-;3707:5;3785:2;3770:18;;;;3757:32;;-1:-1:-1;;;3454:367:1:o;3826:388::-;3894:6;3902;3955:2;3943:9;3934:7;3930:23;3926:32;3923:52;;;3971:1;3968;3961:12;3923:52;4010:9;3997:23;4029:31;4054:5;4029:31;:::i;:::-;4079:5;-1:-1:-1;4136:2:1;4121:18;;4108:32;4149:33;4108:32;4149:33;:::i;:::-;4201:7;4191:17;;;3826:388;;;;;:::o;4219:118::-;4305:5;4298:13;4291:21;4284:5;4281:32;4271:60;;4327:1;4324;4317:12;4342:361;4407:6;4415;4468:2;4456:9;4447:7;4443:23;4439:32;4436:52;;;4484:1;4481;4474:12;4436:52;4529:23;;;-1:-1:-1;4628:2:1;4613:18;;4600:32;4641:30;4600:32;4641:30;:::i;4708:241::-;4764:6;4817:2;4805:9;4796:7;4792:23;4788:32;4785:52;;;4833:1;4830;4823:12;4785:52;4872:9;4859:23;4891:28;4913:5;4891:28;:::i;5456:671::-;5542:6;5550;5558;5566;5619:3;5607:9;5598:7;5594:23;5590:33;5587:53;;;5636:1;5633;5626:12;5587:53;5675:9;5662:23;5694:31;5719:5;5694:31;:::i;:::-;5744:5;-1:-1:-1;5801:2:1;5786:18;;5773:32;5814:33;5773:32;5814:33;:::i;:::-;5866:7;-1:-1:-1;5925:2:1;5910:18;;5897:32;5938:33;5897:32;5938:33;:::i;:::-;5990:7;-1:-1:-1;6049:2:1;6034:18;;6021:32;6062:33;6021:32;6062:33;:::i;:::-;5456:671;;;;-1:-1:-1;5456:671:1;;-1:-1:-1;;5456:671:1:o;6132:184::-;6184:77;6181:1;6174:88;6281:4;6278:1;6271:15;6305:4;6302:1;6295:15;6321:128;6388:9;;;6409:11;;;6406:37;;;6423:18;;:::i;6454:168::-;6527:9;;;6558;;6575:15;;;6569:22;;6555:37;6545:71;;6596:18;;:::i;6627:274::-;6667:1;6693;6683:189;;6728:77;6725:1;6718:88;6829:4;6826:1;6819:15;6857:4;6854:1;6847:15;6683:189;-1:-1:-1;6886:9:1;;6627:274::o;6906:125::-;6971:9;;;6992:10;;;6989:36;;;7005:18;;:::i;7036:230::-;7106:6;7159:2;7147:9;7138:7;7134:23;7130:32;7127:52;;;7175:1;7172;7165:12;7127:52;-1:-1:-1;7220:16:1;;7036:230;-1:-1:-1;7036:230:1:o;7271:184::-;7323:77;7320:1;7313:88;7420:4;7417:1;7410:15;7444:4;7441:1;7434:15;8847:192;8926:13;;8979:34;8968:46;;8958:57;;8948:85;;9029:1;9026;9019:12;8948:85;8847:192;;;:::o;9044:1709::-;9180:6;9233:2;9221:9;9212:7;9208:23;9204:32;9201:52;;;9249:1;9246;9239:12;9201:52;9282:9;9276:16;9315:18;9307:6;9304:30;9301:50;;;9347:1;9344;9337:12;9301:50;9370:22;;9423:4;9415:13;;9411:27;-1:-1:-1;9401:55:1;;9452:1;9449;9442:12;9401:55;9485:2;9479:9;9508:64;9524:47;9564:6;9524:47;:::i;9508:64::-;9594:3;9618:6;9613:3;9606:19;9650:2;9645:3;9641:12;9634:19;;9708:2;9700:4;9692:6;9688:17;9684:2;9680:26;9676:35;9662:49;;9734:7;9726:6;9723:19;9720:39;;;9755:1;9752;9745:12;9720:39;9787:2;9783;9779:11;9768:22;;9799:924;9815:6;9810:3;9807:15;9799:924;;;9897:4;9891:3;9882:7;9878:17;9874:28;9871:48;;;9915:1;9912;9905:12;9871:48;9945:22;;:::i;:::-;10020:10;;10043:22;;10101:43;10140:2;10131:12;;10101:43;:::i;:::-;10096:2;10089:5;10085:14;10078:67;10188:2;10183:3;10179:12;10173:19;10242:7;10238:2;10227:23;10218:7;10215:36;10205:64;;10265:1;10262;10255:12;10205:64;10300:2;10289:14;;10282:31;10349:43;10388:2;10379:12;;10349:43;:::i;:::-;10344:2;10337:5;10333:14;10326:67;10436:3;10431;10427:13;10421:20;10454:33;10479:7;10454:33;:::i;:::-;10518:3;10507:15;;10500:32;10600:3;10591:13;;;10585:20;10625:15;;;10618:32;10663:18;;9841:4;9832:14;;;;10710:2;10701:12;;;;9799:924;;11420:301;11549:3;11587:6;11581:13;11633:6;11626:4;11618:6;11614:17;11609:3;11603:37;11695:1;11659:16;;11684:13;;;-1:-1:-1;11659:16:1;11420:301;-1:-1:-1;11420:301:1:o;11726:245::-;11793:6;11846:2;11834:9;11825:7;11821:23;11817:32;11814:52;;;11862:1;11859;11852:12;11814:52;11894:9;11888:16;11913:28;11935:5;11913:28;:::i;13152:477::-;13301:2;13290:9;13283:21;13264:4;13333:6;13327:13;13376:6;13371:2;13360:9;13356:18;13349:34;13435:6;13430:2;13422:6;13418:15;13413:2;13402:9;13398:18;13392:50;13491:1;13486:2;13477:6;13466:9;13462:22;13458:31;13451:42;13620:2;13550:66;13545:2;13537:6;13533:15;13529:88;13518:9;13514:104;13510:113;13502:121;;;13152:477;;;;:::o
Swarm Source
ipfs://565a8ae0270c5492c7ab9a062f5e6be918bafe3fd432d31bf4d7e92ce14bda71
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.