Address Details
contract

0x3b9FfC0eBb0164Daf0c94F88df29a6e46E984D12

Contract Name
RevoFees
Creator
0xff0944–49a35b at 0xced895–745666
Balance
0 CELO ( )
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
25159428
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
RevoFees




Optimization enabled
false
Compiler version
v0.8.4+commit.c7e474f2




EVM Version
istanbul




Verified at
2022-02-28T08:11:11.688206Z

RevoFees.sol

//SPDX-License-Identifier: MIT
pragma solidity 0.8.4;

import "./ubeswap-farming/contracts/Owned.sol";
import "./IRevoFees.sol";

contract RevoFees is Owned, IRevoFees {
    // compounder fee: a performance fee (taken from farming rewards) to compensate someone who calls 'compound' method
    //  on a Revo Farm Bot. This is necessary because compounders incur gas costs and help users get compound interest
    //  (since the 'compound' method re-invests their farming rewards into the farm)
    uint256 public compounderFeeNumerator;
    uint256 public compounderFeeDenominator;

    // reserve fee: a performance fee (taken from farming rewards) sent to Revo reserves, to fund future development
    uint256 public reserveFeeNumerator;
    uint256 public reserveFeeDenominator;

    event CompounderFeeUpdated(
        address indexed by,
        uint256 compounderFeeNumerator,
        uint256 compounderFeeDenominator
    );
    event ReserveFeeUpdated(
        address indexed by,
        uint256 reserveFeeNumerator,
        uint256 reserveFeeDenominator
    );

    constructor(
        address _owner,
        uint256 _compounderFeeNumerator,
        uint256 _compounderFeeDenominator,
        uint256 _reserveFeeNumerator,
        uint256 _reserveFeeDenominator
    ) Owned(_owner) {
        compounderFeeNumerator = _compounderFeeNumerator;
        compounderFeeDenominator = _compounderFeeDenominator;
        reserveFeeNumerator = _reserveFeeNumerator;
        reserveFeeDenominator = _reserveFeeDenominator;
    }

    function updateCompounderFee(
        uint256 _compounderFeeNumerator,
        uint256 _compounderFeeDenominator
    ) external onlyOwner {
        compounderFeeNumerator = _compounderFeeNumerator;
        compounderFeeDenominator = _compounderFeeDenominator;
        emit CompounderFeeUpdated(
            msg.sender,
            _compounderFeeNumerator,
            _compounderFeeDenominator
        );
    }

    function updateReserveFee(
        uint256 _reserveFeeNumerator,
        uint256 _reserveFeeDenominator
    ) external onlyOwner {
        reserveFeeNumerator = _reserveFeeNumerator;
        reserveFeeDenominator = _reserveFeeDenominator;
        emit ReserveFeeUpdated(
            msg.sender,
            _reserveFeeNumerator,
            _reserveFeeDenominator
        );
    }

    /*
     * Check what the bonus will be for calling 'compound' on a Revo Farm Bot.
     *
     * In the future, bonuses may be issued to compounders that are not taken as performance fees. (Could be governance
     *   tokens, or issued from a community fund.) This may help us lower or eliminate the compounder fee.
     */
    function compounderBonus(TokenAmount memory _interestAccrued)
        external
        pure
        override
        returns (TokenAmount[] memory output)
    {
        return new TokenAmount[](0); // intentionally returns empty list
    }

    function compounderFee(uint256 _interestAccrued)
        external
        view
        override
        returns (uint256)
    {
        return
            (_interestAccrued * compounderFeeNumerator) /
            compounderFeeDenominator;
    }

    function reserveFee(uint256 _interestAccrued)
        external
        view
        override
        returns (uint256)
    {
        return (_interestAccrued * reserveFeeNumerator) / reserveFeeDenominator;
    }

    /*
     * Issue the bonus for calling 'compound' on a Revo Farm Bot.
     */
    function issueCompounderBonus(address recipient) external pure override {
        return; // intentionally does nothing
    }

    /*
     * Check the fee for withdrawing funds from a Revo Farm Bot.
     *
     * Withdrawal fees are used to prevent bad actors from depositing right before 'compound' is called, then withdrawing
     *   right after and taking some of the rewards. (Withdrawal fee should be >= the interest gained from the last time
     *   'compound' was called.)
     *
     * Takes the interest earned the last time 'compound' was called as a parameter. This makes it possible to have dynamic
     *   withdrawal fees.
     *
     * (Note that there is a maximum fee set in the Farm Bot contract to protect
     *   users from unreasonably high withdrawal fees.)
     */
    function withdrawalFee(
        uint256 interestEarnedNumerator,
        uint256 interestEarnedDenominator
    )
        external
        pure
        override
        returns (uint256 feeNumerator, uint256 feeDenominator)
    {
        // 0.25% (ignores interest earned for simplicity)
        feeNumerator = 25;
        feeDenominator = 10000;
    }
}
        

/IRevoFees.sol

//SPDX-License-Identifier: MIT
pragma solidity 0.8.4;

import "./openzeppelin-solidity/contracts/IERC20.sol";

struct TokenAmount {
    IERC20 token;
    uint256 amount;
}

interface IRevoFees {
    function compounderFee(uint256 _interestAccrued)
        external
        view
        returns (uint256);

    function compounderBonus(TokenAmount calldata interestAccrued)
        external
        view
        returns (TokenAmount[] memory);

    function reserveFee(uint256 _interestAccrued)
        external
        view
        returns (uint256);

    function withdrawalFee(
        uint256 interestEarnedNumerator,
        uint256 interestEarnedDenominator
    ) external view returns (uint256 feeNumerator, uint256 feeDenominator);

    function issueCompounderBonus(address recipient) external;
}
          

/openzeppelin-solidity/contracts/IERC20.sol

// 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
    );
}
          

/ubeswap-farming/contracts/Owned.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.3;


// https://docs.synthetix.io/contracts/source/contracts/owned
contract Owned {
    address public owner;
    address public nominatedOwner;

    constructor(address _owner) {
        require(_owner != address(0), "Owner address cannot be 0");
        owner = _owner;
        emit OwnerChanged(address(0), _owner);
    }

    function nominateNewOwner(address _owner) external onlyOwner {
        nominatedOwner = _owner;
        emit OwnerNominated(_owner);
    }

    function acceptOwnership() external {
        require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
        emit OwnerChanged(owner, nominatedOwner);
        owner = nominatedOwner;
        nominatedOwner = address(0);
    }

    modifier onlyOwner {
        _onlyOwner();
        _;
    }

    function _onlyOwner() private view {
        require(msg.sender == owner, "Only the contract owner may perform this action");
    }

    event OwnerNominated(address newOwner);
    event OwnerChanged(address oldOwner, address newOwner);
}
          

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"uint256","name":"_compounderFeeNumerator","internalType":"uint256"},{"type":"uint256","name":"_compounderFeeDenominator","internalType":"uint256"},{"type":"uint256","name":"_reserveFeeNumerator","internalType":"uint256"},{"type":"uint256","name":"_reserveFeeDenominator","internalType":"uint256"}]},{"type":"event","name":"CompounderFeeUpdated","inputs":[{"type":"address","name":"by","internalType":"address","indexed":true},{"type":"uint256","name":"compounderFeeNumerator","internalType":"uint256","indexed":false},{"type":"uint256","name":"compounderFeeDenominator","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnerChanged","inputs":[{"type":"address","name":"oldOwner","internalType":"address","indexed":false},{"type":"address","name":"newOwner","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OwnerNominated","inputs":[{"type":"address","name":"newOwner","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ReserveFeeUpdated","inputs":[{"type":"address","name":"by","internalType":"address","indexed":true},{"type":"uint256","name":"reserveFeeNumerator","internalType":"uint256","indexed":false},{"type":"uint256","name":"reserveFeeDenominator","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"tuple[]","name":"output","internalType":"struct TokenAmount[]","components":[{"type":"address","name":"token","internalType":"contract IERC20"},{"type":"uint256","name":"amount","internalType":"uint256"}]}],"name":"compounderBonus","inputs":[{"type":"tuple","name":"_interestAccrued","internalType":"struct TokenAmount","components":[{"type":"address","name":"token","internalType":"contract IERC20"},{"type":"uint256","name":"amount","internalType":"uint256"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"compounderFee","inputs":[{"type":"uint256","name":"_interestAccrued","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"compounderFeeDenominator","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"compounderFeeNumerator","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[],"name":"issueCompounderBonus","inputs":[{"type":"address","name":"recipient","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"nominateNewOwner","inputs":[{"type":"address","name":"_owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"nominatedOwner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"reserveFee","inputs":[{"type":"uint256","name":"_interestAccrued","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"reserveFeeDenominator","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"reserveFeeNumerator","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateCompounderFee","inputs":[{"type":"uint256","name":"_compounderFeeNumerator","internalType":"uint256"},{"type":"uint256","name":"_compounderFeeDenominator","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateReserveFee","inputs":[{"type":"uint256","name":"_reserveFeeNumerator","internalType":"uint256"},{"type":"uint256","name":"_reserveFeeDenominator","internalType":"uint256"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"feeNumerator","internalType":"uint256"},{"type":"uint256","name":"feeDenominator","internalType":"uint256"}],"name":"withdrawalFee","inputs":[{"type":"uint256","name":"interestEarnedNumerator","internalType":"uint256"},{"type":"uint256","name":"interestEarnedDenominator","internalType":"uint256"}]}]
              

Contract Creation Code

0x60806040523480156200001157600080fd5b50604051620011de380380620011de83398181016040528101906200003791906200017d565b84600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620000ab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000a29062000264565b60405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c6000826040516200011f92919062000237565b60405180910390a15083600281905550826003819055508160048190555080600581905550505050505062000332565b6000815190506200016081620002fe565b92915050565b600081519050620001778162000318565b92915050565b600080600080600060a086880312156200019657600080fd5b6000620001a6888289016200014f565b9550506020620001b98882890162000166565b9450506040620001cc8882890162000166565b9350506060620001df8882890162000166565b9250506080620001f28882890162000166565b9150509295509295909350565b6200020a8162000297565b82525050565b60006200021f60198362000286565b91506200022c82620002d5565b602082019050919050565b60006040820190506200024e6000830185620001ff565b6200025d6020830184620001ff565b9392505050565b600060208201905081810360008301526200027f8162000210565b9050919050565b600082825260208201905092915050565b6000620002a482620002ab565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000600082015250565b620003098162000297565b81146200031557600080fd5b50565b6200032381620002cb565b81146200032f57600080fd5b50565b610e9c80620003426000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063533e03f41161009757806392ce27f81161006657806392ce27f81461024d578063a26436251461027d578063caf4882b1461029b578063f58eee65146102b9576100f5565b8063533e03f4146101eb57806353a47bb71461020757806379ba5097146102255780638da5cb5b1461022f576100f5565b8063232ceecc116100d3578063232ceecc146101645780632a5649921461018257806337d07f461461019e5780634ae2859c146101ba576100f5565b80631627540c146100fa5780631deae18c1461011657806321d6d4af14610146575b600080fd5b610114600480360381019061010f9190610880565b6102e9565b005b610130600480360381019061012b91906108d2565b61036c565b60405161013d9190610b04565b60405180910390f35b61014e610390565b60405161015b9190610b04565b60405180910390f35b61016c610396565b6040516101799190610b04565b60405180910390f35b61019c60048036038101906101979190610880565b61039c565b005b6101b860048036038101906101b391906108fb565b61039f565b005b6101d460048036038101906101cf91906108fb565b610409565b6040516101e2929190610b1f565b60405180910390f35b610205600480360381019061020091906108fb565b61041c565b005b61020f610486565b60405161021c9190610a5e565b60405180910390f35b61022d6104ac565b005b61023761065d565b6040516102449190610a5e565b60405180910390f35b610267600480360381019061026291906108d2565b610681565b6040516102749190610b04565b60405180910390f35b6102856106a5565b6040516102929190610b04565b60405180910390f35b6102a36106ab565b6040516102b09190610b04565b60405180910390f35b6102d360048036038101906102ce91906108a9565b6106b1565b6040516102e09190610aa2565b60405180910390f35b6102f1610735565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22816040516103619190610a5e565b60405180910390a150565b60006005546004548361037f9190610be8565b6103899190610bb7565b9050919050565b60025481565b60055481565b50565b6103a7610735565b81600481905550806005819055503373ffffffffffffffffffffffffffffffffffffffff167ff35610eb852efc886bc5d0a594ebd2fb807b06a2e1c0c10230f5513cb7fa21c583836040516103fd929190610b1f565b60405180910390a25050565b6000806019915061271090509250929050565b610424610735565b81600281905550806003819055503373ffffffffffffffffffffffffffffffffffffffff167ffe1aba736e0f3a6cabe2c2c10aeade49d8231ac34b0e40f77dffd4e1281ce4de838360405161047a929190610b1f565b60405180910390a25050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461053c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161053390610ac4565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516105af929190610a79565b60405180910390a1600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600354600254836106949190610be8565b61069e9190610bb7565b9050919050565b60045481565b60035481565b6060600067ffffffffffffffff8111156106f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561072d57816020015b61071a6107c5565b8152602001906001900390816107125790505b509050919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ba90610ae4565b60405180910390fd5b565b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b60008135905061080481610e21565b92915050565b60008135905061081981610e38565b92915050565b60006040828403121561083157600080fd5b61083b6040610b48565b9050600061084b8482850161080a565b600083015250602061085f8482850161086b565b60208301525092915050565b60008135905061087a81610e4f565b92915050565b60006020828403121561089257600080fd5b60006108a0848285016107f5565b91505092915050565b6000604082840312156108bb57600080fd5b60006108c98482850161081f565b91505092915050565b6000602082840312156108e457600080fd5b60006108f28482850161086b565b91505092915050565b6000806040838503121561090e57600080fd5b600061091c8582860161086b565b925050602061092d8582860161086b565b9150509250929050565b60006109438383610a11565b60408301905092915050565b61095881610c42565b82525050565b600061096982610b7d565b6109738185610b95565b935061097e83610b6d565b8060005b838110156109af5781516109968882610937565b97506109a183610b88565b925050600181019050610982565b5085935050505092915050565b6109c581610c90565b82525050565b60006109d8603583610ba6565b91506109e382610d83565b604082019050919050565b60006109fb602f83610ba6565b9150610a0682610dd2565b604082019050919050565b604082016000820151610a2760008501826109bc565b506020820151610a3a6020850182610a40565b50505050565b610a4981610c86565b82525050565b610a5881610c86565b82525050565b6000602082019050610a73600083018461094f565b92915050565b6000604082019050610a8e600083018561094f565b610a9b602083018461094f565b9392505050565b60006020820190508181036000830152610abc818461095e565b905092915050565b60006020820190508181036000830152610add816109cb565b9050919050565b60006020820190508181036000830152610afd816109ee565b9050919050565b6000602082019050610b196000830184610a4f565b92915050565b6000604082019050610b346000830185610a4f565b610b416020830184610a4f565b9392505050565b6000610b52610b63565b9050610b5e8282610cb4565b919050565b6000604051905090565b6000819050602082019050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b6000610bc282610c86565b9150610bcd83610c86565b925082610bdd57610bdc610d14565b5b828204905092915050565b6000610bf382610c86565b9150610bfe83610c86565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610c3757610c36610ce5565b5b828202905092915050565b6000610c4d82610c66565b9050919050565b6000610c5f82610c42565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610c9b82610ca2565b9050919050565b6000610cad82610c66565b9050919050565b610cbd82610d72565b810181811067ffffffffffffffff82111715610cdc57610cdb610d43565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560008201527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015250565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660008201527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015250565b610e2a81610c42565b8114610e3557600080fd5b50565b610e4181610c54565b8114610e4c57600080fd5b50565b610e5881610c86565b8114610e6357600080fd5b5056fea2646970667358221220cdb65ba4f3d247867e5488e8e9d15ed514ddf85edfc61146186067f0d78ee75c64736f6c634300080400330000000000000000000000001ce0269266a3d50ca0a1a00c205b3afad296e546000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100f55760003560e01c8063533e03f41161009757806392ce27f81161006657806392ce27f81461024d578063a26436251461027d578063caf4882b1461029b578063f58eee65146102b9576100f5565b8063533e03f4146101eb57806353a47bb71461020757806379ba5097146102255780638da5cb5b1461022f576100f5565b8063232ceecc116100d3578063232ceecc146101645780632a5649921461018257806337d07f461461019e5780634ae2859c146101ba576100f5565b80631627540c146100fa5780631deae18c1461011657806321d6d4af14610146575b600080fd5b610114600480360381019061010f9190610880565b6102e9565b005b610130600480360381019061012b91906108d2565b61036c565b60405161013d9190610b04565b60405180910390f35b61014e610390565b60405161015b9190610b04565b60405180910390f35b61016c610396565b6040516101799190610b04565b60405180910390f35b61019c60048036038101906101979190610880565b61039c565b005b6101b860048036038101906101b391906108fb565b61039f565b005b6101d460048036038101906101cf91906108fb565b610409565b6040516101e2929190610b1f565b60405180910390f35b610205600480360381019061020091906108fb565b61041c565b005b61020f610486565b60405161021c9190610a5e565b60405180910390f35b61022d6104ac565b005b61023761065d565b6040516102449190610a5e565b60405180910390f35b610267600480360381019061026291906108d2565b610681565b6040516102749190610b04565b60405180910390f35b6102856106a5565b6040516102929190610b04565b60405180910390f35b6102a36106ab565b6040516102b09190610b04565b60405180910390f35b6102d360048036038101906102ce91906108a9565b6106b1565b6040516102e09190610aa2565b60405180910390f35b6102f1610735565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22816040516103619190610a5e565b60405180910390a150565b60006005546004548361037f9190610be8565b6103899190610bb7565b9050919050565b60025481565b60055481565b50565b6103a7610735565b81600481905550806005819055503373ffffffffffffffffffffffffffffffffffffffff167ff35610eb852efc886bc5d0a594ebd2fb807b06a2e1c0c10230f5513cb7fa21c583836040516103fd929190610b1f565b60405180910390a25050565b6000806019915061271090509250929050565b610424610735565b81600281905550806003819055503373ffffffffffffffffffffffffffffffffffffffff167ffe1aba736e0f3a6cabe2c2c10aeade49d8231ac34b0e40f77dffd4e1281ce4de838360405161047a929190610b1f565b60405180910390a25050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461053c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161053390610ac4565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516105af929190610a79565b60405180910390a1600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600354600254836106949190610be8565b61069e9190610bb7565b9050919050565b60045481565b60035481565b6060600067ffffffffffffffff8111156106f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405190808252806020026020018201604052801561072d57816020015b61071a6107c5565b8152602001906001900390816107125790505b509050919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ba90610ae4565b60405180910390fd5b565b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b60008135905061080481610e21565b92915050565b60008135905061081981610e38565b92915050565b60006040828403121561083157600080fd5b61083b6040610b48565b9050600061084b8482850161080a565b600083015250602061085f8482850161086b565b60208301525092915050565b60008135905061087a81610e4f565b92915050565b60006020828403121561089257600080fd5b60006108a0848285016107f5565b91505092915050565b6000604082840312156108bb57600080fd5b60006108c98482850161081f565b91505092915050565b6000602082840312156108e457600080fd5b60006108f28482850161086b565b91505092915050565b6000806040838503121561090e57600080fd5b600061091c8582860161086b565b925050602061092d8582860161086b565b9150509250929050565b60006109438383610a11565b60408301905092915050565b61095881610c42565b82525050565b600061096982610b7d565b6109738185610b95565b935061097e83610b6d565b8060005b838110156109af5781516109968882610937565b97506109a183610b88565b925050600181019050610982565b5085935050505092915050565b6109c581610c90565b82525050565b60006109d8603583610ba6565b91506109e382610d83565b604082019050919050565b60006109fb602f83610ba6565b9150610a0682610dd2565b604082019050919050565b604082016000820151610a2760008501826109bc565b506020820151610a3a6020850182610a40565b50505050565b610a4981610c86565b82525050565b610a5881610c86565b82525050565b6000602082019050610a73600083018461094f565b92915050565b6000604082019050610a8e600083018561094f565b610a9b602083018461094f565b9392505050565b60006020820190508181036000830152610abc818461095e565b905092915050565b60006020820190508181036000830152610add816109cb565b9050919050565b60006020820190508181036000830152610afd816109ee565b9050919050565b6000602082019050610b196000830184610a4f565b92915050565b6000604082019050610b346000830185610a4f565b610b416020830184610a4f565b9392505050565b6000610b52610b63565b9050610b5e8282610cb4565b919050565b6000604051905090565b6000819050602082019050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b6000610bc282610c86565b9150610bcd83610c86565b925082610bdd57610bdc610d14565b5b828204905092915050565b6000610bf382610c86565b9150610bfe83610c86565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610c3757610c36610ce5565b5b828202905092915050565b6000610c4d82610c66565b9050919050565b6000610c5f82610c42565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610c9b82610ca2565b9050919050565b6000610cad82610c66565b9050919050565b610cbd82610d72565b810181811067ffffffffffffffff82111715610cdc57610cdb610d43565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560008201527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015250565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660008201527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015250565b610e2a81610c42565b8114610e3557600080fd5b50565b610e4181610c54565b8114610e4c57600080fd5b50565b610e5881610c86565b8114610e6357600080fd5b5056fea2646970667358221220cdb65ba4f3d247867e5488e8e9d15ed514ddf85edfc61146186067f0d78ee75c64736f6c63430008040033