Contract
0xd2d63812C72d2455A9613EFDF41FEB4b0B58a7A9
2
Contract Overview
Balance:
0 FTM
FTM Value:
$0.00
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Proxy
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.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)); } } /** * @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"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Config { // function signature of "postProcess()" bytes4 public constant POSTPROCESS_SIG = 0xc2722916; // The base amount of percentage function uint256 public constant PERCENTAGE_BASE = 1 ether; // Handler post-process type. Others should not happen now. enum HandlerType { Token, Custom, Others } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "./interface/IProxy.sol"; import "./interface/IRegistry.sol"; import "./interface/IFeeRuleRegistry.sol"; import "./Config.sol"; import "./Storage.sol"; import "./lib/LibParam.sol"; import "./lib/LibFeeStorage.sol"; /** * @title The entrance of Furucombo * @author Ben Huang */ contract Proxy is IProxy, Storage, Config { using Address for address; using SafeERC20 for IERC20; using LibParam for bytes32; using LibStack for bytes32[]; using Strings for uint256; using LibFeeStorage for mapping(bytes32 => bytes32); event LogBegin( address indexed handler, bytes4 indexed selector, bytes payload ); event LogEnd( address indexed handler, bytes4 indexed selector, bytes result ); event ChargeFee(address indexed tokenIn, uint256 feeAmount); modifier isNotBanned() { require(registry.bannedAgents(address(this)) == 0, "Banned"); _; } modifier isNotHalted() { require(registry.fHalt() == false, "Halted"); _; } address private constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; IRegistry public immutable registry; IFeeRuleRegistry public immutable feeRuleRegistry; constructor(address registry_, address feeRuleRegistry_) { registry = IRegistry(registry_); feeRuleRegistry = IFeeRuleRegistry(feeRuleRegistry_); } /** * @notice Direct transfer from EOA should be reverted. * @dev Callback function will be handled here. */ fallback() external payable isNotHalted isNotBanned isInitialized { // If triggered by a function call, caller should be registered in // registry. // The function call will then be forwarded to the location registered // in registry. require(_isValidCaller(msg.sender), "Invalid caller"); address target = address(bytes20(registry.callers(msg.sender))); bytes memory result = _exec(target, msg.data, type(uint256).max); // return result for aave v2 flashloan() uint256 size = result.length; assembly { let loc := add(result, 0x20) return(loc, size) } } /** * @notice Direct transfer from EOA should be reverted. */ receive() external payable { require(Address.isContract(msg.sender), "Not allowed from EOA"); } /** * @notice Combo execution function. Including three phases: pre-process, * exection and post-process. * @param tos The handlers of combo. * @param configs The configurations of executing cubes. * @param datas The combo datas. * @param ruleIndexes The indexes of rules. */ function batchExec( address[] calldata tos, bytes32[] calldata configs, bytes[] memory datas, uint256[] calldata ruleIndexes ) external payable override isNotHalted isNotBanned { _preProcess(ruleIndexes); _execs(tos, configs, datas); _postProcess(); } /** * @notice The execution interface for callback function to be executed. * @dev This function can only be called through the handler, which makes * the caller become proxy itself. */ function execs( address[] calldata tos, bytes32[] calldata configs, bytes[] memory datas ) external payable override isNotHalted isNotBanned isInitialized { require(msg.sender == address(this), "Does not allow external calls"); _execs(tos, configs, datas); } /** * @notice The execution phase. * @param tos The handlers of combo. * @param configs The configurations of executing cubes. * @param datas The combo datas. */ function _execs( address[] memory tos, bytes32[] memory configs, bytes[] memory datas ) internal { bytes32[256] memory localStack; uint256 index; uint256 counter; require( tos.length == datas.length, "Tos and datas length inconsistent" ); require( tos.length == configs.length, "Tos and configs length inconsistent" ); for (uint256 i = 0; i < tos.length; i++) { address to = tos[i]; bytes32 config = configs[i]; bytes memory data = datas[i]; // Check if the data contains dynamic parameter if (!config.isStatic()) { // If so, trim the exectution data base on the configuration and stack content _trim(data, config, localStack, index); } // Emit the execution log before call bytes4 selector = _getSelector(data); emit LogBegin(to, selector, data); // Check if the output will be referenced afterwards bytes memory result = _exec(to, data, counter); counter++; // Emit the execution log after call emit LogEnd(to, selector, result); if (config.isReferenced()) { // If so, parse the output and place it into local stack uint256 num = config.getReturnNum(); uint256 newIndex = _parse(localStack, result, index); require( newIndex == index + num, "Return num and parsed return num not matched" ); index = newIndex; } // Setup the process to be triggered in the post-process phase _setPostProcess(to); } } /** * @notice Trimming the execution data. * @param data The execution data. * @param config The configuration. * @param localStack The stack the be referenced. * @param index Current element count of localStack. */ function _trim( bytes memory data, bytes32 config, bytes32[256] memory localStack, uint256 index ) internal pure { // Fetch the parameter configuration from config (uint256[] memory refs, uint256[] memory params) = config.getParams(); // Trim the data with the reference and parameters for (uint256 i = 0; i < refs.length; i++) { require(refs[i] < index, "Reference to out of localStack"); bytes32 ref = localStack[refs[i]]; uint256 offset = params[i]; uint256 base = PERCENTAGE_BASE; assembly { let loc := add(add(data, 0x20), offset) let m := mload(loc) // Adjust the value by multiplier if a dynamic parameter is not zero if iszero(iszero(m)) { // Assert no overflow first let p := mul(m, ref) if iszero(eq(div(p, m), ref)) { revert(0, 0) } // require(p / m == ref) ref := div(p, base) } mstore(loc, ref) } } } /** * @notice Parse the return data to the local stack. * @param localStack The local stack to place the return values. * @param ret The return data. * @param index The current tail. */ function _parse( bytes32[256] memory localStack, bytes memory ret, uint256 index ) internal pure returns (uint256 newIndex) { uint256 len = ret.length; // The return value should be multiple of 32-bytes to be parsed. require(len % 32 == 0, "illegal length for _parse"); // Estimate the tail after the process. newIndex = index + len / 32; require(newIndex <= 256, "stack overflow"); assembly { let offset := shl(5, index) // Store the data into localStack for { let i := 0 } lt(i, len) { i := add(i, 0x20) } { mstore( add(localStack, add(i, offset)), mload(add(add(ret, i), 0x20)) ) } } } /** * @notice The execution of a single cube. * @param to_ The handler of cube. * @param data_ The cube execution data. * @param counter_ The current counter of the cube. */ function _exec( address to_, bytes memory data_, uint256 counter_ ) internal returns (bytes memory result) { require(_isValidHandler(to_), "Invalid handler"); bool success; assembly { success := delegatecall( sub(gas(), 5000), to_, add(data_, 0x20), mload(data_), 0, 0 ) let size := returndatasize() result := mload(0x40) mstore( 0x40, add(result, and(add(add(size, 0x20), 0x1f), not(0x1f))) ) mstore(result, size) returndatacopy(add(result, 0x20), 0, size) } if (!success) { if (result.length < 68) revert("_exec"); assembly { result := add(result, 0x04) } if (counter_ == type(uint256).max) { revert(abi.decode(result, (string))); // Don't prepend counter } else { revert( string( abi.encodePacked( counter_.toString(), "_", abi.decode(result, (string)) ) ) ); } } } /** * @notice Setup the post-process. * @param to_ The handler of post-process. */ function _setPostProcess(address to_) internal { // If the stack length equals 0, just skip // If the top is a custom post-process, replace it with the handler // address. if (stack.length == 0) { return; } else if ( stack.peek() == bytes32(bytes12(uint96(HandlerType.Custom))) && bytes4(stack.peek(1)) != 0x00000000 ) { stack.pop(); stack.setAddress(to_); stack.setHandlerType(HandlerType.Custom); } } /// @notice The pre-process phase. function _preProcess( uint256[] memory ruleIndexes_ ) internal virtual isStackEmpty { // Set the sender. _setSender(); // Set the fee collector cache._setFeeCollector(feeRuleRegistry.feeCollector()); // Calculate fee uint256 feeRate = feeRuleRegistry.calFeeRateMulti( _getSender(), ruleIndexes_ ); require(feeRate <= PERCENTAGE_BASE, "fee rate out of range"); cache._setFeeRate(feeRate); if (msg.value > 0 && feeRate > 0) { // Process ether fee uint256 feeEth = _calFee(msg.value, feeRate); // It will fail if fee collector is gnosis contract, because .transfer() will only consume 2300 gas limit. // Replacing .transfer() with .call('') to avoid out of gas address collector = cache._getFeeCollector(); (bool success, ) = collector.call{value: feeEth}(""); require(success, "Send fee to collector failed"); emit ChargeFee(NATIVE_TOKEN, feeEth); } } /// @notice The post-process phase. function _postProcess() internal { // Handler type will be parsed at the beginning. Will send the token back to // user if the handler type is "Token". Will get the handler address and // execute the customized post-process if handler type is "Custom". while (stack.length > 0) { bytes32 top = stack.get(); // Get handler type HandlerType handlerType = HandlerType(uint96(bytes12(top))); if (handlerType == HandlerType.Token) { address addr = address(uint160(uint256(top))); uint256 tokenAmount = IERC20(addr).balanceOf(address(this)); if (tokenAmount > 0) IERC20(addr).safeTransfer(msg.sender, tokenAmount); } else if (handlerType == HandlerType.Custom) { address addr = stack.getAddress(); _exec( addr, abi.encodeWithSelector(POSTPROCESS_SIG), type(uint256).max ); } else { revert("Invalid handler type"); } } // Balance should also be returned to user uint256 amount = address(this).balance; if (amount > 0) payable(msg.sender).transfer(amount); // Reset cached datas cache._resetFeeCollector(); cache._resetFeeRate(); _resetSender(); } /// @notice Check if the handler is valid in registry. function _isValidHandler(address handler) internal view returns (bool) { return registry.isValidHandler(handler); } /// @notice Check if the caller is valid in registry. function _isValidCaller(address caller) internal view returns (bool) { return registry.isValidCaller(caller); } /// @notice Get payload function selector. function _getSelector( bytes memory payload ) internal pure returns (bytes4 selector) { selector = payload[0] | (bytes4(payload[1]) >> 8) | (bytes4(payload[2]) >> 16) | (bytes4(payload[3]) >> 24); } function _calFee( uint256 amount, uint256 feeRate ) internal pure returns (uint256) { return (amount * feeRate) / PERCENTAGE_BASE; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./lib/LibCache.sol"; import "./lib/LibStack.sol"; /// @notice A cache structure composed by a bytes32 array contract Storage { using LibCache for mapping(bytes32 => bytes32); using LibStack for bytes32[]; bytes32[] public stack; mapping(bytes32 => bytes32) public cache; // keccak256 hash of "msg.sender" // prettier-ignore bytes32 public constant MSG_SENDER_KEY = 0xb2f2618cecbbb6e7468cc0f2aa43858ad8d153e0280b22285e28e853bb9d453a; modifier isStackEmpty() { require(stack.length == 0, "Stack not empty"); _; } modifier isInitialized() { require(_getSender() != address(0), "Sender is not initialized"); _; } modifier isNotInitialized() { require(_getSender() == address(0), "Sender is initialized"); _; } function _setSender() internal isNotInitialized { cache.setAddress(MSG_SENDER_KEY, msg.sender); } function _resetSender() internal { cache.setAddress(MSG_SENDER_KEY, address(0)); } function _getSender() internal view returns (address) { return cache.getAddress(MSG_SENDER_KEY); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IFeeRuleRegistry { /* State Variables Getter */ function rules(uint256) external view returns (address); function counter() external view returns (uint256); function basisFeeRate() external view returns (uint256); function feeCollector() external view returns (address); function BASE() external view returns (uint256); /* Restricted Functions */ function setBasisFeeRate(uint256) external; function setFeeCollector(address) external; function registerRule(address rule) external; function unregisterRule(uint256 ruleIndex) external; /* View Functions */ function calFeeRateMulti(address usr, uint256[] calldata ruleIndexes) external view returns (uint256 scaledRate); function calFeeRate(address usr, uint256 ruleIndex) external view returns (uint256 scaledRate); function calFeeRateMultiWithoutBasis(address usr, uint256[] calldata ruleIndexes) external view returns (uint256 scaledRate); function calFeeRateWithoutBasis(address usr, uint256 ruleIndex) external view returns (uint256 scaledRate); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IProxy { function batchExec(address[] calldata tos, bytes32[] calldata configs, bytes[] memory datas, uint256[] calldata ruleIndexes) external payable; function execs(address[] calldata tos, bytes32[] calldata configs, bytes[] memory datas) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IRegistry { function handlers(address) external view returns (bytes32); function callers(address) external view returns (bytes32); function bannedAgents(address) external view returns (uint256); function fHalt() external view returns (bool); function isValidHandler(address handler) external view returns (bool); function isValidCaller(address handler) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library LibCache { function set( mapping(bytes32 => bytes32) storage _cache, bytes32 _key, bytes32 _value ) internal { _cache[_key] = _value; } function setAddress( mapping(bytes32 => bytes32) storage _cache, bytes32 _key, address _value ) internal { _cache[_key] = bytes32(uint256(uint160(_value))); } function setUint256( mapping(bytes32 => bytes32) storage _cache, bytes32 _key, uint256 _value ) internal { _cache[_key] = bytes32(_value); } function getAddress( mapping(bytes32 => bytes32) storage _cache, bytes32 _key ) internal view returns (address ret) { ret = address(uint160(uint256(_cache[_key]))); } function getUint256( mapping(bytes32 => bytes32) storage _cache, bytes32 _key ) internal view returns (uint256 ret) { ret = uint256(_cache[_key]); } function get( mapping(bytes32 => bytes32) storage _cache, bytes32 _key ) internal view returns (bytes32 ret) { ret = _cache[_key]; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./LibCache.sol"; import "../Storage.sol"; library LibFeeStorage { using LibCache for mapping(bytes32 => bytes32); // keccak256 hash of "furucombo.fee.rate" // prettier-ignore bytes32 public constant FEE_RATE_KEY = 0x142183525227cae0e4300fd0fc77d7f3b08ceb0fd9cb2a6c5488668fa0ea5ffa; // keccak256 hash of "furucombo.fee.collector" // prettier-ignore bytes32 public constant FEE_COLLECTOR_KEY = 0x60d7a7cc0a45d852bd613e4f527aaa2e4b81fff918a69a2aab88b6458751d614; function _setFeeRate( mapping(bytes32 => bytes32) storage _cache, uint256 _feeRate ) internal { require(_getFeeRate(_cache) == 0, "Fee rate not zero"); _cache.setUint256(FEE_RATE_KEY, _feeRate); } function _resetFeeRate( mapping(bytes32 => bytes32) storage _cache ) internal { _cache.setUint256(FEE_RATE_KEY, 0); } function _getFeeRate( mapping(bytes32 => bytes32) storage _cache ) internal view returns (uint256) { return _cache.getUint256(FEE_RATE_KEY); } function _setFeeCollector( mapping(bytes32 => bytes32) storage _cache, address _collector ) internal { require( _getFeeCollector(_cache) == address(0), "Fee collector is initialized" ); _cache.setAddress(FEE_COLLECTOR_KEY, _collector); } function _resetFeeCollector( mapping(bytes32 => bytes32) storage _cache ) internal { _cache.setAddress(FEE_COLLECTOR_KEY, address(0)); } function _getFeeCollector( mapping(bytes32 => bytes32) storage _cache ) internal view returns (address) { return _cache.getAddress(FEE_COLLECTOR_KEY); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library LibParam { bytes32 private constant STATIC_MASK = 0x0100000000000000000000000000000000000000000000000000000000000000; bytes32 private constant PARAMS_MASK = 0x0000000000000000000000000000000000000000000000000000000000000001; bytes32 private constant REFS_MASK = 0x00000000000000000000000000000000000000000000000000000000000000FF; bytes32 private constant RETURN_NUM_MASK = 0x00FF000000000000000000000000000000000000000000000000000000000000; uint256 private constant REFS_LIMIT = 22; uint256 private constant PARAMS_SIZE_LIMIT = 64; uint256 private constant RETURN_NUM_OFFSET = 240; function isStatic(bytes32 conf) internal pure returns (bool) { if (conf & STATIC_MASK == 0) return true; else return false; } function isReferenced(bytes32 conf) internal pure returns (bool) { if (getReturnNum(conf) == 0) return false; else return true; } function getReturnNum(bytes32 conf) internal pure returns (uint256 num) { bytes32 temp = (conf & RETURN_NUM_MASK) >> RETURN_NUM_OFFSET; num = uint256(temp); } function getParams( bytes32 conf ) internal pure returns (uint256[] memory refs, uint256[] memory params) { require(!isStatic(conf), "Static params"); uint256 n = REFS_LIMIT; while (conf & REFS_MASK == REFS_MASK && n > 0) { n--; conf = conf >> 8; } require(n > 0, "No dynamic param"); refs = new uint256[](n); params = new uint256[](n); for (uint256 i = 0; i < n; i++) { refs[i] = uint256(conf & REFS_MASK); conf = conf >> 8; } uint256 locCount = 0; for (uint256 k = 0; k < PARAMS_SIZE_LIMIT; k++) { if (conf & PARAMS_MASK != 0) { require(locCount < n, "Location count exceeds ref count"); params[locCount] = k * 32 + 4; locCount++; } conf = conf >> 1; } require(locCount == n, "Location count less than ref count"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../Config.sol"; library LibStack { function setAddress(bytes32[] storage _stack, address _input) internal { _stack.push(bytes32(uint256(uint160(_input)))); } function set(bytes32[] storage _stack, bytes32 _input) internal { _stack.push(_input); } function setHandlerType( bytes32[] storage _stack, Config.HandlerType _input ) internal { _stack.push(bytes12(uint96(_input))); } function getAddress( bytes32[] storage _stack ) internal returns (address ret) { ret = address(uint160(uint256(peek(_stack)))); _stack.pop(); } function getSig(bytes32[] storage _stack) internal returns (bytes4 ret) { ret = bytes4(peek(_stack)); _stack.pop(); } function get(bytes32[] storage _stack) internal returns (bytes32 ret) { ret = peek(_stack); _stack.pop(); } function peek( bytes32[] storage _stack ) internal view returns (bytes32 ret) { uint256 length = _stack.length; require(length > 0, "stack empty"); ret = _stack[length - 1]; } function peek( bytes32[] storage _stack, uint256 _index ) internal view returns (bytes32 ret) { uint256 length = _stack.length; require(length > 0, "stack empty"); require(length > _index, "not enough elements in stack"); ret = _stack[length - _index - 1]; } }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"registry_","type":"address"},{"internalType":"address","name":"feeRuleRegistry_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"ChargeFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"handler","type":"address"},{"indexed":true,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":false,"internalType":"bytes","name":"payload","type":"bytes"}],"name":"LogBegin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"handler","type":"address"},{"indexed":true,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":false,"internalType":"bytes","name":"result","type":"bytes"}],"name":"LogEnd","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"MSG_SENDER_KEY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENTAGE_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POSTPROCESS_SIG","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tos","type":"address[]"},{"internalType":"bytes32[]","name":"configs","type":"bytes32[]"},{"internalType":"bytes[]","name":"datas","type":"bytes[]"},{"internalType":"uint256[]","name":"ruleIndexes","type":"uint256[]"}],"name":"batchExec","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"cache","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tos","type":"address[]"},{"internalType":"bytes32[]","name":"configs","type":"bytes32[]"},{"internalType":"bytes[]","name":"datas","type":"bytes[]"}],"name":"execs","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"feeRuleRegistry","outputs":[{"internalType":"contract IFeeRuleRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stack","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c06040523480156200001157600080fd5b506040516200298038038062002980833981016040819052620000349162000069565b6001600160a01b039182166080521660a052620000a1565b80516001600160a01b03811681146200006457600080fd5b919050565b600080604083850312156200007d57600080fd5b62000088836200004c565b915062000098602084016200004c565b90509250929050565b60805160a05161286d620001136000396000818161040001528181610d760152610e0201526000818160dd0152818161018f015281816102da0152818161045f0152818161057c01528181610749015281816107fb01528181610949015281816109fb0152610bf0015261286d6000f3fe60806040526004361061008a5760003560e01c80637b103999116100595780637b1039991461044d57806387c139431461048157806399eb59b91461049d578063dc9031c4146104ca578063fa2901a5146104ea576100db565b80630f532d18146103a657806341f188e1146103db578063678987bb146103ee578063719385091461043a576100db565b366100db57333b6100d95760405162461bcd60e51b81526020600482015260146024820152734e6f7420616c6c6f7765642066726f6d20454f4160601b60448201526064015b60405180910390fd5b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ea750af66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061015d91906121bf565b1561017a5760405162461bcd60e51b81526004016100d0906121e1565b604051630c81ee5560e11b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631903dcaa90602401602060405180830381865afa1580156101de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102029190612201565b1561021f5760405162461bcd60e51b81526004016100d09061221a565b600061022961051e565b6001600160a01b0316141561027c5760405162461bcd60e51b815260206004820152601960248201527814d95b99195c881a5cc81b9bdd081a5b9a5d1a585b1a5e9959603a1b60448201526064016100d0565b6102853361055a565b6102c25760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21031b0b63632b960911b60448201526064016100d0565b604051637bbf4a3f60e01b81523360048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690637bbf4a3f90602401602060405180830381865afa158015610329573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061034d9190612201565b60601c90506000610399826000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060001992506105f0915050565b8051909150602082018181f35b3480156103b257600080fd5b506103c860008051602061281883398151915281565b6040519081526020015b60405180910390f35b6100d96103e93660046123d8565b610747565b3480156103fa57600080fd5b506104227f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103d2565b6100d9610448366004612497565b610947565b34801561045957600080fd5b506104227f000000000000000000000000000000000000000000000000000000000000000081565b34801561048d57600080fd5b506103c8670de0b6b3a764000081565b3480156104a957600080fd5b506103c86104b836600461252b565b60016020526000908152604090205481565b3480156104d657600080fd5b506103c86104e536600461252b565b610bad565b3480156104f657600080fd5b50610505636139148b60e11b81565b6040516001600160e01b031990911681526020016103d2565b60008051602061281883398151915260005260016020527fe066822ceb6294079ebca45035319f95ccb12306128dbdf5a257f0d1235733c95490565b60405163bb1010e960e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bb1010e9906024015b602060405180830381865afa1580156105c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ea91906121bf565b92915050565b60606105fb84610bce565b6106395760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b2103430b7323632b960891b60448201526064016100d0565b6000806000855160208701886113885a03f490503d6040519250601f19601f6020830101168301604052808352806000602085013e508061073f576044825110156106ae5760405162461bcd60e51b81526020600482015260056024820152645f6578656360d81b60448201526064016100d0565b6004820191506000198314156106eb57818060200190518101906106d29190612574565b60405162461bcd60e51b81526004016100d09190612617565b6106f483610c21565b828060200190518101906107089190612574565b60405160200161071992919061262a565b60408051601f198184030181529082905262461bcd60e51b82526100d091600401612617565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ea750af66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c991906121bf565b156107e65760405162461bcd60e51b81526004016100d0906121e1565b604051630c81ee5560e11b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631903dcaa90602401602060405180830381865afa15801561084a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086e9190612201565b1561088b5760405162461bcd60e51b81526004016100d09061221a565b6108c7828280806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610d2792505050565b61093687878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a925089918291850190849080828437600092019190915250889250611018915050565b61093e6112d2565b50505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ea750af66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c991906121bf565b156109e65760405162461bcd60e51b81526004016100d0906121e1565b604051630c81ee5560e11b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631903dcaa90602401602060405180830381865afa158015610a4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6e9190612201565b15610a8b5760405162461bcd60e51b81526004016100d09061221a565b6000610a9561051e565b6001600160a01b03161415610ae85760405162461bcd60e51b815260206004820152601960248201527814d95b99195c881a5cc81b9bdd081a5b9a5d1a585b1a5e9959603a1b60448201526064016100d0565b333014610b375760405162461bcd60e51b815260206004820152601d60248201527f446f6573206e6f7420616c6c6f772065787465726e616c2063616c6c7300000060448201526064016100d0565b610ba685858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250869250611018915050565b5050505050565b60008181548110610bbd57600080fd5b600091825260209091200154905081565b604051631a98d06960e31b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063d4c68348906024016105a9565b606081610c455750506040805180820190915260018152600360fc1b602082015290565b8160005b8115610c6f5780610c598161267c565b9150610c689050600a836126ad565b9150610c49565b60008167ffffffffffffffff811115610c8a57610c8a612286565b6040519080825280601f01601f191660200182016040528015610cb4576020820181803683370190505b5090505b8415610d1f57610cc96001836126c1565b9150610cd6600a866126d8565b610ce19060306126ec565b60f81b818381518110610cf657610cf6612704565b60200101906001600160f81b031916908160001a905350610d18600a866126ad565b9450610cb8565b949350505050565b60005415610d695760405162461bcd60e51b815260206004820152600f60248201526e537461636b206e6f7420656d70747960881b60448201526064016100d0565b610d7161150e565b610dfe7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df6919061271a565b6001906115a2565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637c4e1d1b610e3761051e565b846040518363ffffffff1660e01b8152600401610e55929190612743565b602060405180830381865afa158015610e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e969190612201565b9050670de0b6b3a7640000811115610ee85760405162461bcd60e51b81526020600482015260156024820152746665652072617465206f7574206f662072616e676560581b60448201526064016100d0565b610ef3600182611642565b600034118015610f035750600081115b15611014576000610f1434836116c0565b90506000610f2260016116e6565b90506000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610f71576040519150601f19603f3d011682016040523d82523d6000602084013e610f76565b606091505b5050905080610fc75760405162461bcd60e51b815260206004820152601c60248201527f53656e642066656520746f20636f6c6c6563746f72206661696c65640000000060448201526064016100d0565b60405183815273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee907ff842076a30ec58e71f31f5ded044f2790b403c5a75bdbfddea03130ee65e1a589060200160405180910390a25050505b5050565b61102061219f565b600080835186511461107e5760405162461bcd60e51b815260206004820152602160248201527f546f7320616e64206461746173206c656e67746820696e636f6e73697374656e6044820152601d60fa1b60648201526084016100d0565b84518651146110db5760405162461bcd60e51b815260206004820152602360248201527f546f7320616e6420636f6e66696773206c656e67746820696e636f6e73697374604482015262195b9d60ea1b60648201526084016100d0565b60005b865181101561093e5760008782815181106110fb576110fb612704565b60200260200101519050600087838151811061111957611119612704565b60200260200101519050600087848151811061113757611137612704565b6020026020010151905061114a8261171b565b61115a5761115a81838989611738565b60006111658261185b565b9050806001600160e01b031916846001600160a01b03167f1e4e60ae3aeb9909ff5e6502e86867f181eadfa0c215186eaf47665909d71eb1846040516111ab9190612617565b60405180910390a360006111c08584896105f0565b9050866111cc8161267c565b975050816001600160e01b031916856001600160a01b03167fc4c643b243548ed55ba2a304003e28a0a82c202984eb15e1d80d811e02dec47f836040516112139190612617565b60405180910390a36112248461190c565b156112b15760ff60f085901c16600061123e8b848c61192a565b905061124a828b6126ec565b81146112ad5760405162461bcd60e51b815260206004820152602c60248201527f52657475726e206e756d20616e64207061727365642072657475726e206e756d60448201526b081b9bdd081b585d18da195960a21b60648201526084016100d0565b9850505b6112ba85611a0e565b505050505080806112ca9061267c565b9150506110de565b600054156114525760006112e66000611a94565b9050600060a082901c600281111561130057611300612799565b9050600081600281111561131657611316612799565b14156113ac576040516370a0823160e01b815230600482015282906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113899190612201565b905080156113a5576113a56001600160a01b0383163383611acc565b505061144b565b60018160028111156113c0576113c0612799565b141561140c5760006113d26000611b23565b6040805160048152602481019091526020810180516001600160e01b0316636139148b60e11b1790529091506113a59082906000196105f0565b60405162461bcd60e51b8152602060048201526014602482015273496e76616c69642068616e646c6572207479706560601b60448201526064016100d0565b50506112d2565b47801561148857604051339082156108fc029083906000818181858888f19350505050158015611486573d6000803e3d6000fd5b505b600160205260007fe3c27e9998c410cbc1bc99c043b2159f2223d768316452dd163c810fbf33d3938190557fb23c0bd6127fbb5e90a415ffb571bd6e4dfe0f2731ea5882703d050f6a0a0c9981905560008051602061281883398151915281527fe066822ceb6294079ebca45035319f95ccb12306128dbdf5a257f0d1235733c9555b50565b600061151861051e565b6001600160a01b0316146115665760405162461bcd60e51b815260206004820152601560248201527414d95b99195c881a5cc81a5b9a5d1a585b1a5e9959605a1b60448201526064016100d0565b6000805160206128188339815191526000526001602052337fe066822ceb6294079ebca45035319f95ccb12306128dbdf5a257f0d1235733c955565b60006115ad836116e6565b6001600160a01b0316146116035760405162461bcd60e51b815260206004820152601c60248201527f46656520636f6c6c6563746f7220697320696e697469616c697a65640000000060448201526064016100d0565b7f60d7a7cc0a45d852bd613e4f527aaa2e4b81fff918a69a2aab88b6458751d61460009081526020839052604090206001600160a01b03821690555050565b61164b82611b43565b1561168c5760405162461bcd60e51b81526020600482015260116024820152704665652072617465206e6f74207a65726f60781b60448201526064016100d0565b7f142183525227cae0e4300fd0fc77d7f3b08ceb0fd9cb2a6c5488668fa0ea5ffa6000908152602092909252604090912055565b6000670de0b6b3a76400006116d583856127af565b6116df91906126ad565b9392505050565b7f60d7a7cc0a45d852bd613e4f527aaa2e4b81fff918a69a2aab88b6458751d6146000908152602082905260408120546105ea565b6000600160f81b821661173057506001919050565b506000919050565b60008061174485611b78565b9150915060005b825181101561093e578383828151811061176757611767612704565b6020026020010151106117bc5760405162461bcd60e51b815260206004820152601e60248201527f5265666572656e636520746f206f7574206f66206c6f63616c537461636b000060448201526064016100d0565b6000858483815181106117d1576117d1612704565b602002602001015161010081106117ea576117ea612704565b60200201519050600083838151811061180557611805612704565b602002602001015190506000670de0b6b3a764000090508160208b01018051801561184157848102858282041461183b57600080fd5b83900494505b5092909252508190506118538161267c565b91505061174b565b600060188260038151811061187257611872612704565b016020015183516001600160f81b031990911690911c906010908490600290811061189f5761189f612704565b016020015184516001600160f81b031990911690911c90600890859060019081106118cc576118cc612704565b016020015185516001600160f81b031990911690911c9085906000906118f4576118f4612704565b01602001516001600160f81b03191617171792915050565b600060f082901c60ff1661192257506000919050565b506001919050565b815160009061193a6020826126d8565b156119875760405162461bcd60e51b815260206004820152601960248201527f696c6c6567616c206c656e67746820666f72205f70617273650000000000000060448201526064016100d0565b6119926020826126ad565b61199c90846126ec565b91506101008211156119e15760405162461bcd60e51b815260206004820152600e60248201526d737461636b206f766572666c6f7760901b60448201526064016100d0565b8260051b60005b82811015611a04576020818701810151838301890152016119e8565b5050509392505050565b600054611a185750565b600160a01b611a276000611e2b565b148015611a485750611a3b60006001611e9a565b6001600160e01b03191615155b1561150b576000805480611a5e57611a5e6127ce565b60019003818190600052602060002001600090559055611a88816000611f6490919063ffffffff16565b61150b60006001611f86565b6000611a9f82611e2b565b905081805480611ab157611ab16127ce565b60019003818190600052602060002001600090559055919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611b1e908490611fc2565b505050565b6000611b2e82611e2b565b60001c905081805480611ab157611ab16127ce565b7f142183525227cae0e4300fd0fc77d7f3b08ceb0fd9cb2a6c5488668fa0ea5ffa6000908152602082905260408120546105ea565b606080611b848361171b565b15611bc15760405162461bcd60e51b815260206004820152600d60248201526c53746174696320706172616d7360981b60448201526064016100d0565b60165b60ff848116148015611bd65750600081115b15611bf45780611be5816127e4565b915050600884901c9350611bc4565b60008111611c375760405162461bcd60e51b815260206004820152601060248201526f4e6f2064796e616d696320706172616d60801b60448201526064016100d0565b8067ffffffffffffffff811115611c5057611c50612286565b604051908082528060200260200182016040528015611c79578160200160208202803683370190505b5092508067ffffffffffffffff811115611c9557611c95612286565b604051908082528060200260200182016040528015611cbe578160200160208202803683370190505b50915060005b81811015611d0957835160ff861690859083908110611ce557611ce5612704565b602090810291909101015260089490941c9380611d018161267c565b915050611cc4565b506000805b6040811015611dc9576001861615611db057828210611d6f5760405162461bcd60e51b815260206004820181905260248201527f4c6f636174696f6e20636f756e7420657863656564732072656620636f756e7460448201526064016100d0565b611d7a8160206127af565b611d859060046126ec565b848381518110611d9757611d97612704565b602090810291909101015281611dac8161267c565b9250505b60019590951c9480611dc18161267c565b915050611d0e565b50818114611e245760405162461bcd60e51b815260206004820152602260248201527f4c6f636174696f6e20636f756e74206c657373207468616e2072656620636f756044820152611b9d60f21b60648201526084016100d0565b5050915091565b805460009080611e6b5760405162461bcd60e51b815260206004820152600b60248201526a737461636b20656d70747960a81b60448201526064016100d0565b82611e776001836126c1565b81548110611e8757611e87612704565b9060005260206000200154915050919050565b815460009080611eda5760405162461bcd60e51b815260206004820152600b60248201526a737461636b20656d70747960a81b60448201526064016100d0565b828111611f295760405162461bcd60e51b815260206004820152601c60248201527f6e6f7420656e6f75676820656c656d656e747320696e20737461636b0000000060448201526064016100d0565b836001611f3685846126c1565b611f4091906126c1565b81548110611f5057611f50612704565b906000526020600020015491505092915050565b8154600181018355600092835260209092206001600160a01b03909116910155565b81816002811115611f9957611f99612799565b81546001810183556000928352602090922060a09190911b6001600160a01b0319169101555050565b6000612017826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120949092919063ffffffff16565b805190915015611b1e578080602001905181019061203591906121bf565b611b1e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016100d0565b6060610d1f848460008585843b6120ed5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016100d0565b600080866001600160a01b0316858760405161210991906127fb565b60006040518083038185875af1925050503d8060008114612146576040519150601f19603f3d011682016040523d82523d6000602084013e61214b565b606091505b509150915061215b828286612166565b979650505050505050565b606083156121755750816116df565b8251156121855782518084602001fd5b8160405162461bcd60e51b81526004016100d09190612617565b604051806120000160405280610100906020820280368337509192915050565b6000602082840312156121d157600080fd5b815180151581146116df57600080fd5b60208082526006908201526512185b1d195960d21b604082015260600190565b60006020828403121561221357600080fd5b5051919050565b60208082526006908201526510985b9b995960d21b604082015260600190565b60008083601f84011261224c57600080fd5b50813567ffffffffffffffff81111561226457600080fd5b6020830191508360208260051b850101111561227f57600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156122c5576122c5612286565b604052919050565b600067ffffffffffffffff8211156122e7576122e7612286565b50601f01601f191660200190565b600082601f83011261230657600080fd5b8135602067ffffffffffffffff8083111561232357612323612286565b8260051b61233283820161229c565b938452858101830193838101908886111561234c57600080fd5b84880192505b858310156123cc5782358481111561236a5760008081fd5b8801603f81018a1361237c5760008081fd5b85810135604061239361238e836122cd565b61229c565b8281528c828486010111156123a85760008081fd5b828285018a8301376000928101890192909252508352509184019190840190612352565b98975050505050505050565b60008060008060008060006080888a0312156123f357600080fd5b873567ffffffffffffffff8082111561240b57600080fd5b6124178b838c0161223a565b909950975060208a013591508082111561243057600080fd5b61243c8b838c0161223a565b909750955060408a013591508082111561245557600080fd5b6124618b838c016122f5565b945060608a013591508082111561247757600080fd5b506124848a828b0161223a565b989b979a50959850939692959293505050565b6000806000806000606086880312156124af57600080fd5b853567ffffffffffffffff808211156124c757600080fd5b6124d389838a0161223a565b909750955060208801359150808211156124ec57600080fd5b6124f889838a0161223a565b9095509350604088013591508082111561251157600080fd5b5061251e888289016122f5565b9150509295509295909350565b60006020828403121561253d57600080fd5b5035919050565b60005b8381101561255f578181015183820152602001612547565b8381111561256e576000848401525b50505050565b60006020828403121561258657600080fd5b815167ffffffffffffffff81111561259d57600080fd5b8201601f810184136125ae57600080fd5b80516125bc61238e826122cd565b8181528560208385010111156125d157600080fd5b6125e2826020830160208601612544565b95945050505050565b60008151808452612603816020860160208601612544565b601f01601f19169290920160200192915050565b6020815260006116df60208301846125eb565b6000835161263c818460208801612544565b605f60f81b908301908152835161265a816001840160208801612544565b01600101949350505050565b634e487b7160e01b600052601160045260246000fd5b600060001982141561269057612690612666565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826126bc576126bc612697565b500490565b6000828210156126d3576126d3612666565b500390565b6000826126e7576126e7612697565b500690565b600082198211156126ff576126ff612666565b500190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561272c57600080fd5b81516001600160a01b03811681146116df57600080fd5b6001600160a01b038316815260406020808301829052835191830182905260009184820191906060850190845b8181101561278c57845183529383019391830191600101612770565b5090979650505050505050565b634e487b7160e01b600052602160045260246000fd5b60008160001904831182151516156127c9576127c9612666565b500290565b634e487b7160e01b600052603160045260246000fd5b6000816127f3576127f3612666565b506000190190565b6000825161280d818460208701612544565b919091019291505056feb2f2618cecbbb6e7468cc0f2aa43858ad8d153e0280b22285e28e853bb9d453aa264697066735822122037dfc521577b57e54a6a3f31b0719e5f4668d6b6c94c519ec45e047dd2d663e564736f6c634300080a00330000000000000000000000004ac58c108f5d932455be6c4c35a9b8eed4572f2a00000000000000000000000040132e775e14ef3a946fa5624468715456fa0be4
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004ac58c108f5d932455be6c4c35a9b8eed4572f2a00000000000000000000000040132e775e14ef3a946fa5624468715456fa0be4
-----Decoded View---------------
Arg [0] : registry_ (address): 0x4ac58c108f5d932455be6c4c35a9b8eed4572f2a
Arg [1] : feeRuleRegistry_ (address): 0x40132e775e14ef3a946fa5624468715456fa0be4
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004ac58c108f5d932455be6c4c35a9b8eed4572f2a
Arg [1] : 00000000000000000000000040132e775e14ef3a946fa5624468715456fa0be4
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Validator ID :
0 FTM
Amount Staked
0
Amount Delegated
0
Staking Total
0
Staking Start Epoch
0
Staking Start Time
0
Proof of Importance
0
Origination Score
0
Validation Score
0
Active
0
Online
0
Downtime
0 s
Address | Amount | claimed Rewards | Created On Epoch | Created On |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.