Contract Overview
Furucombo Proxy v1.6.0
More Info
[ Download CSV Export ]
OVERVIEW
Furucombo Proxy v1.6.0
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
Proxy
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)Audit Report
/** *Submitted for verification at Etherscan.io on 2021-06-21 */ // File: contracts/lib/LibParam.sol pragma solidity ^0.6.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 i = 0; for (uint256 k = 0; k < PARAMS_SIZE_LIMIT; k++) { if (conf & PARAMS_MASK != 0) { require(i < n, "Location count exceeds ref count"); params[i] = k * 32 + 4; i++; } conf = conf >> 1; } require(i == n, "Location count less than ref count"); } } // File: contracts/lib/LibStack.sol pragma solidity ^0.6.0; 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) { require(_stack.length > 0, "stack empty"); ret = _stack[_stack.length - 1]; } } // File: contracts/lib/LibCache.sol pragma solidity ^0.6.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]; } } // File: contracts/Storage.sol pragma solidity ^0.6.0; /// @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; // keccak256 hash of "cube.counter" // prettier-ignore bytes32 public constant CUBE_COUNTER_KEY = 0xf9543f11459ccccd21306c8881aaab675ff49d988c1162fd1dd9bbcdbe4446be; modifier isStackEmpty() { require(stack.length == 0, "Stack not empty"); _; } modifier isCubeCounterZero() { require(_getCubeCounter() == 0, "Cube counter not zero"); _; } 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); } function _addCubeCounter() internal { cache.setUint256(CUBE_COUNTER_KEY, _getCubeCounter() + 1); } function _resetCubeCounter() internal { cache.setUint256(CUBE_COUNTER_KEY, 0); } function _getCubeCounter() internal view returns (uint256) { return cache.getUint256(CUBE_COUNTER_KEY); } } // File: contracts/Config.sol pragma solidity ^0.6.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} } // File: contracts/interface/IRegistry.sol pragma solidity ^0.6.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); } // File: contracts/interface/IProxy.sol pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; interface IProxy { function batchExec(address[] calldata tos, bytes32[] calldata configs, bytes[] memory datas) external payable; function execs(address[] calldata tos, bytes32[] calldata configs, bytes[] memory datas) external payable; } // File: @openzeppelin/contracts/utils/Address.sol // SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <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; // solhint-disable-next-line no-inline-assembly 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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: @openzeppelin/contracts/math/SafeMath.sol pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol pragma solidity >=0.6.0 <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); } // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol pragma solidity >=0.6.0 <0.8.0; /** * @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 SafeMath for uint256; 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' // solhint-disable-next-line max-line-length 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).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _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 // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: contracts/Proxy.sol pragma solidity ^0.6.0; /** * @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; modifier isNotBanned() { require(registry.bannedAgents(address(this)) == 0, "Banned"); _; } modifier isNotHalted() { require(registry.fHalt() == false, "Halted"); _; } IRegistry public immutable registry; constructor(address _registry) public { registry = IRegistry(_registry); } /** * @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); // 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. */ function batchExec( address[] calldata tos, bytes32[] calldata configs, bytes[] memory datas ) external payable override isNotHalted isNotBanned { _preProcess(); _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 = 0; 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++) { bytes32 config = configs[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(datas[i], config, localStack, index); } // Check if the output will be referenced afterwards bytes memory result = _exec(tos[i], datas[i]); 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(tos[i]); } } /** * @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. */ function _exec(address _to, bytes memory _data) internal returns (bytes memory result) { require(_isValidHandler(_to), "Invalid handler"); _addCubeCounter(); assembly { let succeeded := 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) switch iszero(succeeded) case 1 { revert(add(result, 0x20), size) } } } /** * @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))) ) { stack.pop(); // Check if the handler is already set. if (bytes4(stack.peek()) != 0x00000000) stack.setAddress(_to); stack.setHandlerType(HandlerType.Custom); } } /// @notice The pre-process phase. function _preProcess() internal virtual isStackEmpty isCubeCounterZero { // Set the sender. _setSender(); } /// @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 amount = IERC20(addr).balanceOf(address(this)); if (amount > 0) IERC20(addr).safeTransfer(msg.sender, amount); } else if (handlerType == HandlerType.Custom) { address addr = stack.getAddress(); _exec(addr, abi.encodeWithSelector(POSTPROCESS_SIG)); } else { revert("Invalid handler type"); } } // Balance should also be returned to user uint256 amount = address(this).balance; if (amount > 0) msg.sender.transfer(amount); // Reset the msg.sender and cube counter _resetSender(); _resetCubeCounter(); } /// @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); } }
Contract Security Audit
- Certora - April 12th, 2021 - Security Audit Report
- PeckShield - May 4th, 2021 - Security Audit Report
[{"inputs":[{"internalType":"address","name":"_registry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"CUBE_COUNTER_KEY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"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[]"}],"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":"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
60a060405234801561001057600080fd5b50604051611ee6380380611ee683398101604081905261002f91610044565b60601b6001600160601b031916608052610072565b600060208284031215610055578081fd5b81516001600160a01b038116811461006b578182fd5b9392505050565b60805160601c611e2b6100bb6000398060c15280610184528061029652806104b352806105e352806106a652806107d0528061089352806109f65280610a8c5250611e2b6000f3fe60806040526004361061008a5760003560e01c80637b103999116100595780637b103999146103d657806387c13943146103f857806399eb59b91461040d578063dc9031c41461042d578063fa2901a51461044d576100bf565b80630f532d18146103705780631413dc7d1461039b57806338c5c08e146103b057806371938509146103c3576100bf565b366100bf576100983361046f565b6100bd5760405162461bcd60e51b81526004016100b490611a14565b60405180910390fd5b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ea750af66040518163ffffffff1660e01b815260040160206040518083038186803b15801561011857600080fd5b505afa15801561012c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101509190611758565b1561016d5760405162461bcd60e51b81526004016100b490611b35565b604051630c81ee5560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631903dcaa906101b99030906004016117c4565b60206040518083038186803b1580156101d157600080fd5b505afa1580156101e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102099190611790565b156102265760405162461bcd60e51b81526004016100b490611a42565b6000610230610479565b6001600160a01b031614156102575760405162461bcd60e51b81526004016100b490611842565b61026033610499565b61027c5760405162461bcd60e51b81526004016100b4906118d1565b604051637bbf4a3f60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637bbf4a3f906102cb9033906004016117c4565b60206040518083038186803b1580156102e357600080fd5b505afa1580156102f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031b9190611790565b60601c90506060610363826000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061053e92505050565b8051909150602082018181f35b34801561037c57600080fd5b506103856105bd565b60405161039291906117f1565b60405180910390f35b3480156103a757600080fd5b506103856105cf565b6100bd6103be366004611674565b6105e1565b6100bd6103d1366004611674565b6107ce565b3480156103e257600080fd5b506103eb6109f4565b60405161039291906117c4565b34801561040457600080fd5b50610385610a18565b34801561041957600080fd5b50610385610428366004611778565b610a24565b34801561043957600080fd5b50610385610448366004611778565b610a36565b34801561045957600080fd5b50610462610a54565b60405161039291906117fa565b803b15155b919050565b60006104946001600080516020611db6833981519152610a5f565b905090565b60405163bb1010e960e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bb1010e9906104e89085906004016117c4565b60206040518083038186803b15801561050057600080fd5b505afa158015610514573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105389190611758565b92915050565b606061054983610a72565b6105655760405162461bcd60e51b81526004016100b490611a89565b61056d610ac1565b600080835160208501866113885a03f43d6040519250601f19601f6020830101168301604052808352806000602085013e8115600181146105ad576105b4565b8160208501fd5b50505092915050565b600080516020611db683398151915281565b600080516020611dd683398151915281565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ea750af66040518163ffffffff1660e01b815260040160206040518083038186803b15801561063a57600080fd5b505afa15801561064e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106729190611758565b1561068f5760405162461bcd60e51b81526004016100b490611b35565b604051630c81ee5560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631903dcaa906106db9030906004016117c4565b60206040518083038186803b1580156106f357600080fd5b505afa158015610707573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072b9190611790565b156107485760405162461bcd60e51b81526004016100b490611a42565b610750610ae8565b6107bf85858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250869250610b35915050565b6107c7610c82565b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ea750af66040518163ffffffff1660e01b815260040160206040518083038186803b15801561082757600080fd5b505afa15801561083b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085f9190611758565b1561087c5760405162461bcd60e51b81526004016100b490611b35565b604051630c81ee5560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631903dcaa906108c89030906004016117c4565b60206040518083038186803b1580156108e057600080fd5b505afa1580156108f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109189190611790565b156109355760405162461bcd60e51b81526004016100b490611a42565b600061093f610479565b6001600160a01b031614156109665760405162461bcd60e51b81526004016100b490611842565b3330146109855760405162461bcd60e51b81526004016100b490611ab2565b6107c785858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250869250610b35915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b670de0b6b3a764000081565b60016020526000908152604090205481565b60008181548110610a4357fe5b600091825260209091200154905081565b636139148b60e11b81565b6000908152602091909152604090205490565b604051631a98d06960e31b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d4c68348906104e89085906004016117c4565b610ae6600080516020611dd6833981519152610adb610e23565b600191908201610e3e565b565b60005415610b085760405162461bcd60e51b81526004016100b490611be3565b610b10610e23565b15610b2d5760405162461bcd60e51b81526004016100b490611928565b610ae6610e50565b610b3d6115a2565b60008251855114610b605760405162461bcd60e51b81526004016100b490611ba2565b8351855114610b815760405162461bcd60e51b81526004016100b490611c43565b60005b8551811015610c7a576000858281518110610b9b57fe5b60200260200101519050610bae81610e9a565b610bd157610bd1858381518110610bc157fe5b6020026020010151828686610eb7565b6060610c03888481518110610be257fe5b6020026020010151878581518110610bf657fe5b602002602001015161053e565b9050610c0e82610f90565b15610c54576000610c1e83610faf565b90506000610c2d878488610fb8565b90508186018114610c505760405162461bcd60e51b81526004016100b490611ae9565b9450505b610c70888481518110610c6357fe5b6020026020010151611035565b5050600101610b84565b505050505050565b60005415610dda576000610c9660006110a7565b9050600060a082901c6002811115610caa57fe5b90506000816002811115610cba57fe5b1415610d64576040516370a0823160e01b815282906000906001600160a01b038316906370a0823190610cf19030906004016117c4565b60206040518083038186803b158015610d0957600080fd5b505afa158015610d1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d419190611790565b90508015610d5d57610d5d6001600160a01b03831633836110d9565b5050610dd3565b6001816002811115610d7257fe5b1415610dbb576000610d846000611134565b6040805160048152602481019091526020810180516001600160e01b0316636139148b60e11b179052909150610d5d90829061053e565b60405162461bcd60e51b81526004016100b490611879565b5050610c82565b478015610e1057604051339082156108fc029083906000818181858888f19350505050158015610e0e573d6000803e3d6000fd5b505b610e1861114e565b610e20611169565b50565b60006104946001600080516020611dd6833981519152610a5f565b60009182526020929092526040902055565b6000610e5a610479565b6001600160a01b031614610e805760405162461bcd60e51b81526004016100b4906118f9565b610ae66001600080516020611db683398151915233611184565b6000600160f81b8216610eaf57506001610474565b506000610474565b606080610ec3856111a2565b9150915060005b8251811015610f875783838281518110610ee057fe5b602002602001015110610f055760405162461bcd60e51b81526004016100b490611cbd565b600085848381518110610f1457fe5b60200260200101516101008110610f2757fe5b602002015190506000838381518110610f3c57fe5b602002602001015190506000670de0b6b3a764000090508160208b010180518015610f78578481028582820414610f7257600080fd5b83900494505b50929092525050600101610eca565b50505050505050565b6000610f9b82610faf565b610fa757506000610474565b506001610474565b60f01c60ff1690565b81516000906020810615610fde5760405162461bcd60e51b81526004016100b490611c0c565b60208104830191506101008211156110085760405162461bcd60e51b81526004016100b490611b7a565b8260051b60005b8281101561102b5760208187018101518383018901520161100f565b5050509392505050565b60005461104157610e20565b600160a01b6110506000611363565b1415610e2057600080548061106157fe5b600190038181906000526020600020016000905590556110816000611363565b6001600160e01b0319161561109b5761109b6000826113a8565b610e20600060016113ca565b60006110b282611363565b9050818054806110be57fe5b60019003818190600052602060002001600090559055919050565b61112f8363a9059cbb60e01b84846040516024016110f89291906117d8565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611400565b505050565b600061113f82611363565b60001c9050818054806110be57fe5b610ae66001600080516020611db68339815191526000611184565b610ae66001600080516020611dd68339815191526000610e3e565b6000918252602092909252604090206001600160a01b039091169055565b6060806111ae83610e9a565b156111cb5760405162461bcd60e51b81526004016100b490611a62565b60165b60ff8481161480156111e05750600081115b156111f55760089390931c92600019016111ce565b600081116112155760405162461bcd60e51b81526004016100b4906118a7565b8067ffffffffffffffff8111801561122c57600080fd5b50604051908082528060200260200182016040528015611256578160200160208202803683370190505b5092508067ffffffffffffffff8111801561127057600080fd5b5060405190808252806020026020018201604052801561129a578160200160208202803683370190505b50915060005b818110156112d557835160ff8616908590839081106112bb57fe5b602090810291909101015260089490941c936001016112a0565b506000805b604081101561133c5760018616156113305782821061130b5760405162461bcd60e51b81526004016100b490611999565b8060200260040184838151811061131e57fe5b60209081029190910101526001909101905b600195861c95016112da565b5081811461135c5760405162461bcd60e51b81526004016100b490611957565b5050915091565b80546000906113845760405162461bcd60e51b81526004016100b490611b55565b81548290600019810190811061139657fe5b90600052602060002001549050919050565b8154600181018355600092835260209092206001600160a01b03909116910155565b818160028111156113d757fe5b81546001810183556000928352602090922060a09190911b6001600160a01b0319169101555050565b6060611455826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661148f9092919063ffffffff16565b80519091501561112f57808060200190518101906114739190611758565b61112f5760405162461bcd60e51b81526004016100b490611cf4565b606061149e84846000856114a8565b90505b9392505050565b6060824710156114ca5760405162461bcd60e51b81526004016100b4906119ce565b6114d38561046f565b6114ef5760405162461bcd60e51b81526004016100b490611c86565b60006060866001600160a01b0316858760405161150c91906117a8565b60006040518083038185875af1925050503d8060008114611549576040519150601f19603f3d011682016040523d82523d6000602084013e61154e565b606091505b509150915061155e828286611569565b979650505050505050565b606083156115785750816114a1565b8251156115885782518084602001fd5b8160405162461bcd60e51b81526004016100b4919061180f565b604051806120000160405280610100906020820280368337509192915050565b60008083601f8401126115d3578182fd5b50813567ffffffffffffffff8111156115ea578182fd5b602083019150836020808302850101111561160457600080fd5b9250929050565b600082601f83011261161b578081fd5b813567ffffffffffffffff811115611631578182fd5b611644601f8201601f1916602001611d3e565b915080825283602082850101111561165b57600080fd5b8060208401602084013760009082016020015292915050565b60008060008060006060868803121561168b578081fd5b853567ffffffffffffffff808211156116a2578283fd5b6116ae89838a016115c2565b90975095506020915087820135818111156116c7578384fd5b6116d38a828b016115c2565b9096509450506040880135818111156116ea578384fd5b88019050601f810189136116fc578283fd5b803561170f61170a82611d65565b611d3e565b81815283810190838501865b84811015611744576117328e88843589010161160b565b8452928601929086019060010161171b565b505080955050505050509295509295909350565b600060208284031215611769578081fd5b815180151581146114a1578182fd5b600060208284031215611789578081fd5b5035919050565b6000602082840312156117a1578081fd5b5051919050565b600082516117ba818460208701611d85565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b90815260200190565b6001600160e01b031991909116815260200190565b600060208252825180602084015261182e816040850160208701611d85565b601f01601f19169190910160400192915050565b60208082526019908201527f53656e646572206973206e6f7420696e697469616c697a656400000000000000604082015260600190565b602080825260149082015273496e76616c69642068616e646c6572207479706560601b604082015260600190565b60208082526010908201526f4e6f2064796e616d696320706172616d60801b604082015260600190565b6020808252600e908201526d24b73b30b634b21031b0b63632b960911b604082015260600190565b60208082526015908201527414d95b99195c881a5cc81a5b9a5d1a585b1a5e9959605a1b604082015260600190565b6020808252601590820152744375626520636f756e746572206e6f74207a65726f60581b604082015260600190565b60208082526022908201527f4c6f636174696f6e20636f756e74206c657373207468616e2072656620636f756040820152611b9d60f21b606082015260800190565b6020808252818101527f4c6f636174696f6e20636f756e7420657863656564732072656620636f756e74604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252601490820152734e6f7420616c6c6f7765642066726f6d20454f4160601b604082015260600190565b60208082526006908201526510985b9b995960d21b604082015260600190565b6020808252600d908201526c53746174696320706172616d7360981b604082015260600190565b6020808252600f908201526e24b73b30b634b2103430b7323632b960891b604082015260600190565b6020808252601d908201527f446f6573206e6f7420616c6c6f772065787465726e616c2063616c6c73000000604082015260600190565b6020808252602c908201527f52657475726e206e756d20616e64207061727365642072657475726e206e756d60408201526b081b9bdd081b585d18da195960a21b606082015260800190565b60208082526006908201526512185b1d195960d21b604082015260600190565b6020808252600b908201526a737461636b20656d70747960a81b604082015260600190565b6020808252600e908201526d737461636b206f766572666c6f7760901b604082015260600190565b60208082526021908201527f546f7320616e64206461746173206c656e67746820696e636f6e73697374656e6040820152601d60fa1b606082015260800190565b6020808252600f908201526e537461636b206e6f7420656d70747960881b604082015260600190565b60208082526019908201527f696c6c6567616c206c656e67746820666f72205f706172736500000000000000604082015260600190565b60208082526023908201527f546f7320616e6420636f6e66696773206c656e67746820696e636f6e73697374604082015262195b9d60ea1b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252601e908201527f5265666572656e636520746f206f7574206f66206c6f63616c537461636b0000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60405181810167ffffffffffffffff81118282101715611d5d57600080fd5b604052919050565b600067ffffffffffffffff821115611d7b578081fd5b5060209081020190565b60005b83811015611da0578181015183820152602001611d88565b83811115611daf576000848401525b5050505056feb2f2618cecbbb6e7468cc0f2aa43858ad8d153e0280b22285e28e853bb9d453af9543f11459ccccd21306c8881aaab675ff49d988c1162fd1dd9bbcdbe4446bea264697066735822122051db33abd03600483453f645abc594ed426f00b8264511097e052adb605fff3a64736f6c634300060c003300000000000000000000000084faf5b559f58d651e51300c5a7d078cb964e691
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000084faf5b559f58d651e51300c5a7d078cb964e691
-----Decoded View---------------
Arg [0] : _registry (address): 0x84faf5b559f58d651e51300c5a7d078cb964e691
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000084faf5b559f58d651e51300c5a7d078cb964e691
Deployed ByteCode Sourcemap
26952:10585:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28402:30;28421:10;28402:18;:30::i;:::-;28394:63;;;;-1:-1:-1;;;28394:63:0;;;;;;;:::i;:::-;;;;;;;;;26952:10585;;27265:8;-1:-1:-1;;;;;27265:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:25;27257:44;;;;-1:-1:-1;;;27257:44:0;;;;;;;:::i;:::-;27143:36:::1;::::0;-1:-1:-1;;;27143:36:0;;-1:-1:-1;;;;;27143:8:0::1;:21;::::0;::::1;::::0;:36:::1;::::0;27173:4:::1;::::0;27143:36:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41:::0;27135:60:::1;;;;-1:-1:-1::0;;;27135:60:0::1;;;;;;;:::i;:::-;5671:1:::2;5647:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;5647:26:0::2;;;5639:64;;;;-1:-1:-1::0;;;5639:64:0::2;;;;;;;:::i;:::-;27889:26:::3;27904:10;27889:14;:26::i;:::-;27881:53;;;;-1:-1:-1::0;;;27881:53:0::3;;;;;;;:::i;:::-;27980:28;::::0;-1:-1:-1;;;27980:28:0;;27947:14:::3;::::0;-1:-1:-1;;;;;27980:8:0::3;:16;::::0;::::3;::::0;:28:::3;::::0;27997:10:::3;::::0;27980:28:::3;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;27964:46;;27947:63;;28021:19;28043:23;28049:6;28057:8;;28043:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::3;::::0;;;;-1:-1:-1;28043:5:0::3;::::0;-1:-1:-1;;;28043:23:0:i:3;:::-;28144:13:::0;;28021:45;;-1:-1:-1;28215:4:0::3;28203:17:::0;::::3;28144:13:::0;28203:17;28234::::3;5072:107:::0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5253:109;;;;;;;;;;;;;:::i;28747:272::-;;;;;;:::i;:::-;;:::i;29242:313::-;;;;;;:::i;:::-;;:::i;27329:35::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;6785:49::-;;;;;;;;;;;;;:::i;4960:40::-;;;;;;;;;;-1:-1:-1;4960:40:0;;;;;:::i;:::-;;:::i;4931:22::-;;;;;;;;;;-1:-1:-1;4931:22:0;;;;;:::i;:::-;;:::i;6678:51::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;8620:422::-;8987:20;;9026:8;;8620:422;;;;:::o;6081:112::-;6126:7;6153:32;:5;-1:-1:-1;;;;;;;;;;;6153:16:0;:32::i;:::-;6146:39;;6081:112;:::o;37409:125::-;37496:30;;-1:-1:-1;;;37496:30:0;;37472:4;;-1:-1:-1;;;;;37496:8:0;:22;;;;:30;;37519:6;;37496:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;37489:37;37409:125;-1:-1:-1;;37409:125:0:o;34035:896::-;34119:19;34164:20;34180:3;34164:15;:20::i;:::-;34156:48;;;;-1:-1:-1;;;34156:48:0;;;;;;;:::i;:::-;34215:17;:15;:17::i;:::-;34458:1;34438;34413:5;34407:12;34383:4;34376:5;34372:16;34350:3;34326:4;34319:5;34315:16;34284:190;34500:16;34548:4;34542:11;34532:21;;34663:4;34659:9;34652:4;34645;34639;34635:15;34631:26;34627:42;34619:6;34615:55;34592:4;34567:118;34714:4;34706:6;34699:20;34770:4;34767:1;34760:4;34752:6;34748:17;34733:42;34805:9;34798:17;34838:1;34833:80;;;;34791:122;;34833:80;34889:4;34882;34874:6;34870:17;34863:31;34791:122;;;;34252:672;;;;:::o;5072:107::-;-1:-1:-1;;;;;;;;;;;5072:107:0;:::o;5253:109::-;-1:-1:-1;;;;;;;;;;;5253:109:0;:::o;28747:272::-;27265:8;-1:-1:-1;;;;;27265:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:25;27257:44;;;;-1:-1:-1;;;27257:44:0;;;;;;;:::i;:::-;27143:36:::1;::::0;-1:-1:-1;;;27143:36:0;;-1:-1:-1;;;;;27143:8:0::1;:21;::::0;::::1;::::0;:36:::1;::::0;27173:4:::1;::::0;27143:36:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41:::0;27135:60:::1;;;;-1:-1:-1::0;;;27135:60:0::1;;;;;;;:::i;:::-;28935:13:::2;:11;:13::i;:::-;28959:27;28966:3;;28959:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;;28959:27:0::2;::::0;;::::2;::::0;;::::2;::::0;;;;;;;;;;;;;-1:-1:-1;28971:7:0;;-1:-1:-1;28971:7:0;;;;28959:27;::::2;::::0;28971:7;;28959:27;28971:7;28959:27;::::2;;::::0;::::2;::::0;;;;-1:-1:-1;28980:5:0;;-1:-1:-1;28959:6:0::2;::::0;-1:-1:-1;;28959:27:0:i:2;:::-;28997:14;:12;:14::i;:::-;28747:272:::0;;;;;:::o;29242:313::-;27265:8;-1:-1:-1;;;;;27265:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:25;27257:44;;;;-1:-1:-1;;;27257:44:0;;;;;;;:::i;:::-;27143:36:::1;::::0;-1:-1:-1;;;27143:36:0;;-1:-1:-1;;;;;27143:8:0::1;:21;::::0;::::1;::::0;:36:::1;::::0;27173:4:::1;::::0;27143:36:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41:::0;27135:60:::1;;;;-1:-1:-1::0;;;27135:60:0::1;;;;;;;:::i;:::-;5671:1:::2;5647:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;5647:26:0::2;;;5639:64;;;;-1:-1:-1::0;;;5639:64:0::2;;;;;;;:::i;:::-;29448:10:::3;29470:4;29448:27;29440:69;;;;-1:-1:-1::0;;;29440:69:0::3;;;;;;;:::i;:::-;29520:27;29527:3;;29520:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::3;::::0;;;;-1:-1:-1;;29520:27:0::3;::::0;;::::3;::::0;;::::3;::::0;;;;;;;;;;;;;-1:-1:-1;29532:7:0;;-1:-1:-1;29532:7:0;;;;29520:27;::::3;::::0;29532:7;;29520:27;29532:7;29520:27;::::3;;::::0;::::3;::::0;;;;-1:-1:-1;29541:5:0;;-1:-1:-1;29520:6:0::3;::::0;-1:-1:-1;;29520:27:0:i:3;27329:35::-:0;;;:::o;6785:49::-;6827:7;6785:49;:::o;4960:40::-;;;;;;;;;;;;;:::o;4931:22::-;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4931:22:0;:::o;6678:51::-;-1:-1:-1;;;6678:51:0;:::o;4106:203::-;4232:11;4286:12;;;;;;;;;;;;;4106:203::o;37213:129::-;37302:32;;-1:-1:-1;;;37302:32:0;;37278:4;;-1:-1:-1;;;;;37302:8:0;:23;;;;:32;;37326:7;;37302:32;;;:::i;6201:112::-;6248:57;-1:-1:-1;;;;;;;;;;;6283:17:0;:15;:17::i;:::-;6303:1;;6248:57;6283:21;;6248:16;:57::i;:::-;6201:112::o;35682:130::-;5414:5;:12;:17;5406:45;;;;-1:-1:-1;;;5406:45:0;;;;;;;:::i;:::-;5527:17:::1;:15;:17::i;:::-;:22:::0;5519:56:::1;;;;-1:-1:-1::0;;;5519:56:0::1;;;;;;;:::i;:::-;35792:12:::2;:10;:12::i;29760:1522::-:0;29900:30;;:::i;:::-;29941:13;30007:5;:12;29993:3;:10;:26;29971:109;;;;-1:-1:-1;;;29971:109:0;;;;;;;:::i;:::-;30127:7;:14;30113:3;:10;:28;30091:113;;;;-1:-1:-1;;;30091:113:0;;;;;;;:::i;:::-;30220:9;30215:1060;30239:3;:10;30235:1;:14;30215:1060;;;30271:14;30288:7;30296:1;30288:10;;;;;;;;;;;;;;30271:27;;30379:17;:6;:15;:17::i;:::-;30374:197;;30513:42;30519:5;30525:1;30519:8;;;;;;;;;;;;;;30529:6;30537:10;30549:5;30513;:42::i;:::-;30651:19;30673:23;30679:3;30683:1;30679:6;;;;;;;;;;;;;;30687:5;30693:1;30687:8;;;;;;;;;;;;;;30673:5;:23::i;:::-;30651:45;;30715:21;:6;:19;:21::i;:::-;30711:437;;;30831:11;30845:21;:6;:19;:21::i;:::-;30831:35;;30885:16;30904:33;30911:10;30923:6;30931:5;30904:6;:33::i;:::-;30885:52;;31006:3;30998:5;:11;30986:8;:23;30956:141;;;;-1:-1:-1;;;30956:141:0;;;;;;;:::i;:::-;31124:8;-1:-1:-1;;30711:437:0;31240:23;31256:3;31260:1;31256:6;;;;;;;;;;;;;;31240:15;:23::i;:::-;-1:-1:-1;;30251:3:0;;30215:1060;;;;29760:1522;;;;;:::o;35861:1284::-;36172:1;36157:12;:16;36150:724;;36190:11;36204;:5;:9;:11::i;:::-;36190:25;-1:-1:-1;36263:23:0;36301:20;;;;36289:33;;;;;;;;36263:59;-1:-1:-1;36356:17:0;36341:11;:32;;;;;;;;;36337:526;;;36475:37;;-1:-1:-1;;;36475:37:0;;36433:3;;36394:12;;-1:-1:-1;;;;;36475:22:0;;;;;:37;;36506:4;;36475:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36458:54;-1:-1:-1;36535:10:0;;36531:61;;36547:45;-1:-1:-1;;;;;36547:25:0;;36573:10;36585:6;36547:25;:45::i;:::-;36337:526;;;;;36633:18;36618:11;:33;;;;;;;;;36614:249;;;36672:12;36687:18;:5;:16;:18::i;:::-;36736:39;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;36736:39:0;-1:-1:-1;;;36736:39:0;;;36672:33;;-1:-1:-1;36724:52:0;;36672:33;;36724:5;:52::i;36614:249::-;36817:30;;-1:-1:-1;;;36817:30:0;;;;;;;:::i;36614:249::-;36150:724;;;;;36955:21;36991:10;;36987:43;;37003:27;;:10;;:27;;;;;37023:6;;37003:27;;;;37023:6;37003:10;:27;;;;;;;;;;;;;;;;;;;;;36987:43;37093:14;:12;:14::i;:::-;37118:19;:17;:19::i;:::-;35861:1284;:::o;6423:119::-;6473:7;6500:34;:5;-1:-1:-1;;;;;;;;;;;6500:16:0;:34::i;3912:186::-;4075:15;4060:12;;;;;;;;;;;:30;3912:186::o;5858:111::-;5802:1;5778:12;:10;:12::i;:::-;-1:-1:-1;;;;;5778:26:0;;5770:60;;;;-1:-1:-1;;;5770:60:0;;;;;;;:::i;:::-;5917:44:::1;:5;-1:-1:-1::0;;;;;;;;;;;5950:10:0::1;5917:16;:44::i;736:148::-:0;791:4;-1:-1:-1;;;812:18:0;;808:68;;-1:-1:-1;844:4:0;837:11;;808:68;-1:-1:-1;871:5:0;864:12;;31547:1214;31771:21;31794:23;31821:18;:6;:16;:18::i;:::-;31770:69;;;;31915:9;31910:844;31934:4;:11;31930:1;:15;31910:844;;;31985:5;31975:4;31980:1;31975:7;;;;;;;;;;;;;;:15;31967:58;;;;-1:-1:-1;;;31967:58:0;;;;;;;:::i;:::-;32040:11;32054:10;32065:4;32070:1;32065:7;;;;;;;;;;;;;;32054:19;;;;;;;;;;;32040:33;;32088:14;32105:6;32112:1;32105:9;;;;;;;;;;;;;;32088:26;;32129:12;6827:7;32129:30;;32234:6;32227:4;32221;32217:15;32213:28;32274:3;32268:10;32399:1;32392:9;32382:2;;32491:3;32488:1;32484:11;32541:3;32537:1;32534;32530:9;32527:18;32517:2;;32584:1;32581;32574:12;32517:2;32663:12;;;;-1:-1:-1;32382:2:0;-1:-1:-1;32712:16:0;;;;-1:-1:-1;;31947:3:0;;31910:844;;;;31547:1214;;;;;;:::o;892:152::-;951:4;972:18;985:4;972:12;:18::i;:::-;968:68;;-1:-1:-1;1004:5:0;997:12;;968:68;-1:-1:-1;1032:4:0;1025:11;;1052:181;724:3;1150:45;;;;1052:181::o;32990:885::-;33171:10;;33128:16;;33280:2;33171:10;33274:8;:13;33266:51;;;;-1:-1:-1;;;33266:51:0;;;;;;;:::i;:::-;33402:2;33396:3;:8;33388:5;:16;33377:27;;33435:3;33423:8;:15;;33415:42;;;;-1:-1:-1;;;33415:42:0;;;;;;;:::i;:::-;33513:5;33510:1;33506:13;33612:1;33580:277;33635:3;33632:1;33629:10;33580:277;;;33817:4;33804:11;;;33800:22;;33794:29;33756:14;;;33740:31;;33711:131;33664:12;33580:277;;;33584:44;;33477:391;;;;;;:::o;35045:589::-;35257:5;:12;35253:374;;35291:7;;35253:374;-1:-1:-1;;;35333:12:0;:5;:10;:12::i;:::-;:60;35315:312;;;35420:5;:11;;;;;;;;;;;;;;;;;;;;;;;;35510:12;:5;:10;:12::i;:::-;-1:-1:-1;;;;;;35503:34:0;;35499:61;;35539:21;:5;35556:3;35539:16;:21::i;:::-;35575:40;:5;35596:18;35575:20;:40::i;3077:130::-;3134:11;3164:12;3169:6;3164:4;:12::i;:::-;3158:18;;3187:6;:12;;;;;;;;;;;;;;;;;;;;;;;;3077:130;;;:::o;23739:177::-;23822:86;23842:5;23872:23;;;23897:2;23901:5;23849:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;23849:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;23849:58:0;-1:-1:-1;;;;;;23849:58:0;;;;;;;;;;23822:19;:86::i;:::-;23739:177;;;:::o;2734:187::-;2816:11;2875:12;2880:6;2875:4;:12::i;:::-;2867:21;;2845:45;;2901:6;:12;;;;;;5977:96;6021:44;:5;-1:-1:-1;;;;;;;;;;;6038:14:0;6021:16;:44::i;6321:94::-;6370:37;:5;-1:-1:-1;;;;;;;;;;;6387:16:0;6370;:37::i;3700:204::-;3863:33;3848:12;;;;;;;;;;;-1:-1:-1;;;;;3871:24:0;;;3848:48;;3700:204::o;1241:977::-;1324:21;1347:23;1397:14;1406:4;1397:8;:14::i;:::-;1396:15;1388:41;;;;-1:-1:-1;;;1388:41:0;;;;;;;:::i;:::-;616:2;1473:108;378:66;1480:16;;;:29;:38;;;;;1517:1;1513;:5;1480:38;1473:108;;;1568:1;1560:9;;;;;-1:-1:-1;;1535:3:0;1473:108;;;1603:1;1599;:5;1591:34;;;;-1:-1:-1;;;1591:34:0;;;;;;;:::i;:::-;1657:1;1643:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1643:16:0;;1636:23;;1693:1;1679:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1679:16:0;;1670:25;;1711:9;1706:125;1730:1;1726;:5;1706:125;;;1753:7;;378:66;1771:16;;;1753:4;;1758:1;;1753:7;;;;;;;;;;;;;;;:35;1818:1;1810:9;;;;;1733:3;;1706:125;;;;1841:9;1870;1865:282;670:2;1885:1;:21;1865:282;;;259:66;1932:18;;:23;1928:177;;1988:1;1984;:5;1976:50;;;;-1:-1:-1;;;1976:50:0;;;;;;;:::i;:::-;2057:1;2061:2;2057:6;2066:1;2057:10;2045:6;2052:1;2045:9;;;;;;;;;;;;;;;;;:22;2086:3;;;;;1928:177;2134:1;2126:9;;;;1908:3;1865:282;;;;2170:1;2165;:6;2157:53;;;;-1:-1:-1;;;2157:53:0;;;;;;;:::i;:::-;1241:977;;;;;:::o;3215:210::-;3342:13;;3305:11;;3334:41;;;;-1:-1:-1;;;3334:41:0;;;;;;;:::i;:::-;3399:13;;3392:6;;-1:-1:-1;;3399:17:0;;;3392:25;;;;;;;;;;;;;;3386:31;;3215:210;;;:::o;2317:136::-;2399:46;;;;;;;2411:33;2399:46;;;;;;;-1:-1:-1;;;;;2419:24:0;;;2399:46;;;2317:136::o;2571:155::-;2682:6;2709;2702:14;;;;;;;;2682:36;;;;;;;-1:-1:-1;2682:36:0;;;;;;;2694:23;;;;;-1:-1:-1;;;;;;2682:36:0;;;;-1:-1:-1;;2571:155:0:o;26044:761::-;26468:23;26494:69;26522:4;26494:69;;;;;;;;;;;;;;;;;26502:5;-1:-1:-1;;;;;26494:27:0;;;:69;;;;;:::i;:::-;26578:17;;26468:95;;-1:-1:-1;26578:21:0;26574:224;;26720:10;26709:30;;;;;;;;;;;;:::i;:::-;26701:85;;;;-1:-1:-1;;;26701:85:0;;;;;;;:::i;11538:195::-;11641:12;11673:52;11695:6;11703:4;11709:1;11712:12;11673:21;:52::i;:::-;11666:59;;11538:195;;;;;;:::o;12590:530::-;12717:12;12775:5;12750:21;:30;;12742:81;;;;-1:-1:-1;;;12742:81:0;;;;;;;:::i;:::-;12842:18;12853:6;12842:10;:18::i;:::-;12834:60;;;;-1:-1:-1;;;12834:60:0;;;;;;;:::i;:::-;12968:12;12982:23;13009:6;-1:-1:-1;;;;;13009:11:0;13029:5;13037:4;13009:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12967:75;;;;13060:52;13078:7;13087:10;13099:12;13060:17;:52::i;:::-;13053:59;12590:530;-1:-1:-1;;;;;;;12590:530:0:o;14126:742::-;14241:12;14270:7;14266:595;;;-1:-1:-1;14301:10:0;14294:17;;14266:595;14415:17;;:21;14411:439;;14678:10;14672:17;14739:15;14726:10;14722:2;14718:19;14711:44;14626:148;14821:12;14814:20;;-1:-1:-1;;;14814:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;:::o;23:352::-;;;153:3;146:4;138:6;134:17;130:27;120:2;;-1:-1;;161:12;120:2;-1:-1;191:20;;231:18;220:30;;217:2;;;-1:-1;;253:12;217:2;297:4;289:6;285:17;273:29;;348:3;297:4;;332:6;328:17;289:6;314:32;;311:41;308:2;;;365:1;;355:12;308:2;113:262;;;;;:::o;1904:440::-;;2005:3;1998:4;1990:6;1986:17;1982:27;1972:2;;-1:-1;;2013:12;1972:2;2060:6;2047:20;28593:18;28585:6;28582:30;28579:2;;;-1:-1;;28615:12;28579:2;2082:64;28688:9;28669:17;;-1:-1;;28665:33;28756:4;28746:15;2082:64;:::i;:::-;2073:73;;2166:6;2159:5;2152:21;2270:3;28756:4;2261:6;2194;2252:16;;2249:25;2246:2;;;2287:1;;2277:12;2246:2;30742:6;28756:4;2194:6;2190:17;28756:4;2228:5;2224:16;30719:30;30798:1;30780:16;;;28756:4;30780:16;30773:27;2228:5;1965:379;-1:-1;;1965:379::o;2630:957::-;;;;;;2872:2;2860:9;2851:7;2847:23;2843:32;2840:2;;;-1:-1;;2878:12;2840:2;2936:17;2923:31;2974:18;;2966:6;2963:30;2960:2;;;-1:-1;;2996:12;2960:2;3034:80;3106:7;3097:6;3086:9;3082:22;3034:80;:::i;:::-;3016:98;;-1:-1;3016:98;-1:-1;3179:2;;-1:-1;3164:18;;;3151:32;3192:30;;;3189:2;;;-1:-1;;3225:12;3189:2;3263:80;3335:7;3326:6;3315:9;3311:22;3263:80;:::i;:::-;3245:98;;-1:-1;3245:98;-1:-1;;3408:2;3393:18;;3380:32;3421:30;;;3418:2;;;-1:-1;;3454:12;3418:2;3539:22;;;-1:-1;896:4;884:17;;880:27;-1:-1;870:2;;-1:-1;;911:12;870:2;958:6;945:20;980:89;995:73;1061:6;995:73;:::i;:::-;980:89;:::i;:::-;1097:21;;;1154:14;;;;1129:17;;;-1:-1;1234:242;1259:6;1256:1;1253:13;1234:242;;;1366:46;1408:3;3179:2;1342:3;1329:17;1133:6;1317:30;;1366:46;:::i;:::-;1354:59;;1427:14;;;;1455;;;;1281:1;1274:9;1234:242;;;1238:14;;3474:97;;;;;;;;2834:753;;;;;;;;:::o;3594:257::-;;3706:2;3694:9;3685:7;3681:23;3677:32;3674:2;;;-1:-1;;3712:12;3674:2;1571:6;1565:13;31277:5;29524:13;29517:21;31255:5;31252:32;31242:2;;-1:-1;;31288:12;3858:241;;3962:2;3950:9;3941:7;3937:23;3933:32;3930:2;;;-1:-1;;3968:12;3930:2;-1:-1;1692:20;;3924:175;-1:-1;3924:175::o;4106:263::-;;4221:2;4209:9;4200:7;4196:23;4192:32;4189:2;;;-1:-1;;4227:12;4189:2;-1:-1;1840:13;;4183:186;-1:-1;4183:186::o;14937:271::-;;5560:5;28865:12;5671:52;5716:6;5711:3;5704:4;5697:5;5693:16;5671:52;:::i;:::-;5735:16;;;;;15071:137;-1:-1;;15071:137::o;15215:222::-;-1:-1;;;;;29842:54;;;;5114:37;;15342:2;15327:18;;15313:124::o;15689:333::-;-1:-1;;;;;29842:54;;;;5114:37;;16008:2;15993:18;;5234:37;15844:2;15829:18;;15815:207::o;16029:222::-;5234:37;;;16156:2;16141:18;;16127:124::o;16258:218::-;-1:-1;;;;;;29690:78;;;;5352:36;;16383:2;16368:18;;16354:122::o;16746:310::-;;16893:2;16914:17;16907:47;6075:5;28865:12;29304:6;16893:2;16882:9;16878:18;29292:19;6169:52;6214:6;29332:14;16882:9;29332:14;16893:2;6195:5;6191:16;6169:52;:::i;:::-;28688:9;31159:14;-1:-1;;31155:28;6233:39;;;;29332:14;6233:39;;16864:192;-1:-1;;16864:192::o;17063:416::-;17263:2;17277:47;;;6509:2;17248:18;;;29292:19;6545:27;29332:14;;;6525:48;6592:12;;;17234:245::o;17486:416::-;17686:2;17700:47;;;6843:2;17671:18;;;29292:19;-1:-1;;;29332:14;;;6859:43;6921:12;;;17657:245::o;17909:416::-;18109:2;18123:47;;;7172:2;18094:18;;;29292:19;-1:-1;;;29332:14;;;7188:39;7246:12;;;18080:245::o;18332:416::-;18532:2;18546:47;;;7497:2;18517:18;;;29292:19;-1:-1;;;29332:14;;;7513:37;7569:12;;;18503:245::o;18755:416::-;18955:2;18969:47;;;7820:2;18940:18;;;29292:19;-1:-1;;;29332:14;;;7836:44;7899:12;;;18926:245::o;19178:416::-;19378:2;19392:47;;;8150:2;19363:18;;;29292:19;-1:-1;;;29332:14;;;8166:44;8229:12;;;19349:245::o;19601:416::-;19801:2;19815:47;;;8480:2;19786:18;;;29292:19;8516:34;29332:14;;;8496:55;-1:-1;;;8571:12;;;8564:26;8609:12;;;19772:245::o;20024:416::-;20224:2;20238:47;;;20209:18;;;29292:19;8896:34;29332:14;;;8876:55;8950:12;;;20195:245::o;20447:416::-;20647:2;20661:47;;;9201:2;20632:18;;;29292:19;9237:34;29332:14;;;9217:55;-1:-1;;;9292:12;;;9285:30;9334:12;;;20618:245::o;20870:416::-;21070:2;21084:47;;;9585:2;21055:18;;;29292:19;-1:-1;;;29332:14;;;9601:43;9663:12;;;21041:245::o;21293:416::-;21493:2;21507:47;;;9914:1;21478:18;;;29292:19;-1:-1;;;29332:14;;;9929:29;9977:12;;;21464:245::o;21716:416::-;21916:2;21930:47;;;10228:2;21901:18;;;29292:19;-1:-1;;;29332:14;;;10244:36;10299:12;;;21887:245::o;22139:416::-;22339:2;22353:47;;;10550:2;22324:18;;;29292:19;-1:-1;;;29332:14;;;10566:38;10623:12;;;22310:245::o;22562:416::-;22762:2;22776:47;;;10874:2;22747:18;;;29292:19;10910:31;29332:14;;;10890:52;10961:12;;;22733:245::o;22985:416::-;23185:2;23199:47;;;11212:2;23170:18;;;29292:19;11248:34;29332:14;;;11228:55;-1:-1;;;11303:12;;;11296:36;11351:12;;;23156:245::o;23408:416::-;23608:2;23622:47;;;11602:1;23593:18;;;29292:19;-1:-1;;;29332:14;;;11617:29;11665:12;;;23579:245::o;23831:416::-;24031:2;24045:47;;;11916:2;24016:18;;;29292:19;-1:-1;;;29332:14;;;11932:34;11985:12;;;24002:245::o;24254:416::-;24454:2;24468:47;;;12236:2;24439:18;;;29292:19;-1:-1;;;29332:14;;;12252:37;12308:12;;;24425:245::o;24677:416::-;24877:2;24891:47;;;12559:2;24862:18;;;29292:19;12595:34;29332:14;;;12575:55;-1:-1;;;12650:12;;;12643:25;12687:12;;;24848:245::o;25100:416::-;25300:2;25314:47;;;12938:2;25285:18;;;29292:19;-1:-1;;;29332:14;;;12954:38;13011:12;;;25271:245::o;25523:416::-;25723:2;25737:47;;;13262:2;25708:18;;;29292:19;13298:27;29332:14;;;13278:48;13345:12;;;25694:245::o;25946:416::-;26146:2;26160:47;;;13596:2;26131:18;;;29292:19;13632:34;29332:14;;;13612:55;-1:-1;;;13687:12;;;13680:27;13726:12;;;26117:245::o;26369:416::-;26569:2;26583:47;;;13977:2;26554:18;;;29292:19;14013:31;29332:14;;;13993:52;14064:12;;;26540:245::o;26792:416::-;26992:2;27006:47;;;14315:2;26977:18;;;29292:19;14351:32;29332:14;;;14331:53;14403:12;;;26963:245::o;27215:416::-;27415:2;27429:47;;;14654:2;27400:18;;;29292:19;14690:34;29332:14;;;14670:55;-1:-1;;;14745:12;;;14738:34;14791:12;;;27386:245::o;27867:256::-;27929:2;27923:9;27955:17;;;28030:18;28015:34;;28051:22;;;28012:62;28009:2;;;28087:1;;28077:12;28009:2;27929;28096:22;27907:216;;-1:-1;27907:216::o;28130:313::-;;28298:18;28290:6;28287:30;28284:2;;;-1:-1;;28320:12;28284:2;-1:-1;28365:4;28353:17;;;28418:15;;28221:222::o;30815:268::-;30880:1;30887:101;30901:6;30898:1;30895:13;30887:101;;;30968:11;;;30962:18;30949:11;;;30942:39;30923:2;30916:10;30887:101;;;31003:6;31000:1;30997:13;30994:2;;;30880:1;31059:6;31054:3;31050:16;31043:27;30994:2;;30864:219;;;:::o
Swarm Source
ipfs://51db33abd03600483453f645abc594ed426f00b8264511097e052adb605fff3a
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.
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.