ETH Price: $3,736.12 (+18.79%)
Gas: 21 Gwei

Contract

0x9FD9946E526357B35D95Bcb4b388614be4cFd4AC
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Transmute And Cl...157442732022-10-14 5:30:47585 days ago1665725447IN
Alchemix Finance: alETH Transmuter
0 ETH0.0019938315
Transmute And Cl...157370992022-10-13 5:26:47586 days ago1665638807IN
Alchemix Finance: alETH Transmuter
0 ETH0.0015731411.86646971
Transmute And Cl...157225912022-10-11 4:50:23588 days ago1665463823IN
Alchemix Finance: alETH Transmuter
0 ETH0.0028022622.61475846
Stake157225892022-10-11 4:49:59588 days ago1665463799IN
Alchemix Finance: alETH Transmuter
0 ETH0.0029637424.41063626
Transmute And Cl...156908052022-10-06 18:19:35592 days ago1665080375IN
Alchemix Finance: alETH Transmuter
0 ETH0.0017530214.14722255
Stake156908022022-10-06 18:18:59592 days ago1665080339IN
Alchemix Finance: alETH Transmuter
0 ETH0.001593413.12394581
Transmute And Cl...156712092022-10-04 0:29:23595 days ago1664843363IN
Alchemix Finance: alETH Transmuter
0 ETH0.0015563612.56010492
Stake156712072022-10-04 0:28:59595 days ago1664843339IN
Alchemix Finance: alETH Transmuter
0 ETH0.0012914512.38212348
Stake156539692022-10-01 14:40:23598 days ago1664635223IN
Alchemix Finance: alETH Transmuter
0 ETH0.001335411
Transmute And Cl...156324112022-09-28 14:23:59601 days ago1664375039IN
Alchemix Finance: alETH Transmuter
0 ETH0.0016108613
Stake156324082022-09-28 14:23:23601 days ago1664375003IN
Alchemix Finance: alETH Transmuter
0 ETH0.001355913
Harvest156232802022-09-27 7:43:47602 days ago1664264627IN
Alchemix Finance: alETH Transmuter
0 ETH0.0047530738.34457852
Stake156111042022-09-25 14:52:11604 days ago1664117531IN
Alchemix Finance: alETH Transmuter
0 ETH0.000983398.09967483
Transmute And Cl...156051272022-09-24 18:52:35604 days ago1664045555IN
Alchemix Finance: alETH Transmuter
0 ETH0.000779715.88151571
Transmute And Cl...155797532022-09-21 5:28:59608 days ago1663738139IN
Alchemix Finance: alETH Transmuter
0 ETH0.000613194.94860343
Stake155797492022-09-21 5:28:11608 days ago1663738091IN
Alchemix Finance: alETH Transmuter
0 ETH0.000493424.73026199
Stake155638262022-09-18 23:54:11610 days ago1663545251IN
Alchemix Finance: alETH Transmuter
0 ETH0.000443844.25643166
Stake155619912022-09-18 17:43:23611 days ago1663523003IN
Alchemix Finance: alETH Transmuter
0 ETH0.0013653811.24697162
Transmute And Cl...155543192022-09-17 15:53:35612 days ago1663430015IN
Alchemix Finance: alETH Transmuter
0 ETH0.0016405213.23934179
Stake155487942022-09-16 21:17:35612 days ago1663363055IN
Alchemix Finance: alETH Transmuter
0 ETH0.000988728.14516385
Transmute And Cl...155371282022-09-15 5:42:21614 days ago1663220541IN
Alchemix Finance: alETH Transmuter
0 ETH0.0017719814.30023867
Stake155294372022-09-13 22:19:46615 days ago1663107586IN
Alchemix Finance: alETH Transmuter
0 ETH0.0013521912.9644579
Stake155248472022-09-13 4:09:44616 days ago1663042184IN
Alchemix Finance: alETH Transmuter
0 ETH0.000844286.95455806
Stake155173402022-09-11 22:29:57617 days ago1662935397IN
Alchemix Finance: alETH Transmuter
0 ETH0.0004946818.90201873
Transmute And Cl...155173402022-09-11 22:29:57617 days ago1662935397IN
Alchemix Finance: alETH Transmuter
0 ETH0.002342218.90201873
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
157442732022-10-14 5:30:47585 days ago1665725447
Alchemix Finance: alETH Transmuter
0.29553227 ETH
157442732022-10-14 5:30:47585 days ago1665725447
Alchemix Finance: alETH Transmuter
0.29553227 ETH
157370992022-10-13 5:26:47586 days ago1665638807
Alchemix Finance: alETH Transmuter
11.62490625 ETH
157370992022-10-13 5:26:47586 days ago1665638807
Alchemix Finance: alETH Transmuter
11.62490625 ETH
157225912022-10-11 4:50:23588 days ago1665463823
Alchemix Finance: alETH Transmuter
25.48436238 ETH
157225912022-10-11 4:50:23588 days ago1665463823
Alchemix Finance: alETH Transmuter
25.48436238 ETH
156908052022-10-06 18:19:35592 days ago1665080375
Alchemix Finance: alETH Transmuter
15.71508919 ETH
156908052022-10-06 18:19:35592 days ago1665080375
Alchemix Finance: alETH Transmuter
15.71508919 ETH
156712092022-10-04 0:29:23595 days ago1664843363
Alchemix Finance: alETH Transmuter
31.1243306 ETH
156712092022-10-04 0:29:23595 days ago1664843363
Alchemix Finance: alETH Transmuter
31.1243306 ETH
156324112022-09-28 14:23:59601 days ago1664375039
Alchemix Finance: alETH Transmuter
21.89905257 ETH
156324112022-09-28 14:23:59601 days ago1664375039
Alchemix Finance: alETH Transmuter
21.89905257 ETH
156051272022-09-24 18:52:35604 days ago1664045555
Alchemix Finance: alETH Transmuter
20.3719582 ETH
156051272022-09-24 18:52:35604 days ago1664045555
Alchemix Finance: alETH Transmuter
20.3719582 ETH
155797532022-09-21 5:28:59608 days ago1663738139
Alchemix Finance: alETH Transmuter
20.41959063 ETH
155797532022-09-21 5:28:59608 days ago1663738139
Alchemix Finance: alETH Transmuter
20.41959063 ETH
155543192022-09-17 15:53:35612 days ago1663430015
Alchemix Finance: alETH Transmuter
13.79362771 ETH
155543192022-09-17 15:53:35612 days ago1663430015
Alchemix Finance: alETH Transmuter
13.79362771 ETH
155371282022-09-15 5:42:21614 days ago1663220541
Alchemix Finance: alETH Transmuter
15.86959857 ETH
155371282022-09-15 5:42:21614 days ago1663220541
Alchemix Finance: alETH Transmuter
15.86959857 ETH
155173402022-09-11 22:29:57617 days ago1662935397
Alchemix Finance: alETH Transmuter
19.19331137 ETH
155173402022-09-11 22:29:57617 days ago1662935397
Alchemix Finance: alETH Transmuter
19.19331137 ETH
154934082022-09-08 0:23:54621 days ago1662596634
Alchemix Finance: alETH Transmuter
70.20034299 ETH
154934082022-09-08 0:23:54621 days ago1662596634
Alchemix Finance: alETH Transmuter
70.20034299 ETH
154907112022-09-07 14:01:50622 days ago1662559310
Alchemix Finance: alETH Transmuter
0.06320787 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TransmuterEth

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 999999 runs

Other Settings:
default evmVersion
File 1 of 19 : TransmuterEth.sol
pragma solidity 0.6.12;

import "@openzeppelin/contracts/GSN/Context.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "./interfaces/IERC20Burnable.sol";
import {YearnVaultAdapterWithIndirection} from "./adapters/YearnVaultAdapterWithIndirection.sol";
import {VaultWithIndirection} from "./libraries/alchemist/VaultWithIndirection.sol";
import {ITransmuter} from "./interfaces/ITransmuter.sol";
import {IWETH9} from "./interfaces/IWETH9.sol";

//    ___    __        __                _               ___                              __         _ 
//   / _ |  / / ____  / /  ___   __ _   (_) __ __       / _ \  ____ ___   ___ ___   ___  / /_  ___  (_)
//  / __ | / / / __/ / _ \/ -_) /  ' \ / /  \ \ /      / ___/ / __// -_) (_-</ -_) / _ \/ __/ (_-< _
// /_/ |_|/_/  \__/ /_//_/\__/ /_/_/_//_/  /_\_\      /_/    /_/   \__/ /___/\__/ /_//_/\__/ /___/(_)
//
// .___________..______           ___      .__   __.      _______..___  ___.  __    __  .___________. _______ .______
// |           ||   _  \         /   \     |  \ |  |     /       ||   \/   | |  |  |  | |           ||   ____||   _  \
// `---|  |----`|  |_)  |       /  ^  \    |   \|  |    |   (----`|  \  /  | |  |  |  | `---|  |----`|  |__   |  |_)  |
//     |  |     |      /       /  /_\  \   |  . `  |     \   \    |  |\/|  | |  |  |  |     |  |     |   __|  |      /
//     |  |     |  |\  \----. /  _____  \  |  |\   | .----)   |   |  |  |  | |  `--'  |     |  |     |  |____ |  |\  \----.
//     |__|     | _| `._____|/__/     \__\ |__| \__| |_______/    |__|  |__|  \______/      |__|     |_______|| _| `._____|
/**
 * @dev Implementation of the {IERC20Burnable} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20Burnable-approve}.
 */
contract TransmuterEth is Context {
    using SafeMath for uint256;
    using SafeERC20 for IERC20Burnable;
    using Address for address;
    using VaultWithIndirection for VaultWithIndirection.Data;
    using VaultWithIndirection for VaultWithIndirection.List;

    address public constant ZERO_ADDRESS = address(0);
    uint256 public transmutationPeriod;

    address public alToken;
    address public token;

    mapping(address => uint256) public depositedAlTokens;
    mapping(address => uint256) public tokensInBucket;
    mapping(address => uint256) public realisedTokens;
    mapping(address => uint256) public lastDividendPoints;

    mapping(address => bool) public userIsKnown;
    mapping(uint256 => address) public userList;
    uint256 public nextUser;

    uint256 public totalSupplyAltokens;
    uint256 public buffer;
    uint256 public lastDepositBlock;

    ///@dev values needed to calculate the distribution of base asset in proportion for alTokens staked
    uint256 public pointMultiplier = 10e18;

    uint256 public totalDividendPoints;
    uint256 public unclaimedDividends;

    /// @dev alchemist addresses whitelisted
    mapping (address => bool) public whiteList;

    /// @dev addresses whitelisted to run keepr jobs (harvest)
    mapping (address => bool) public keepers;

    /// @dev The threshold above which excess funds will be deployed to yield farming activities
    uint256 public plantableThreshold = 50000000000000000000; // 50 ETH

    /// @dev The % margin to trigger planting or recalling of funds
    uint256 public plantableMargin = 5;

    /// @dev The address of the account which currently has administrative capabilities over this contract.
    address public governance;

    /// @dev The address of the pending governance.
    address public pendingGovernance;

    /// @dev The address of the account which can perform emergency activities
    address public sentinel;

    /// @dev A flag indicating if deposits and flushes should be halted and if all parties should be able to recall
    /// from the active vault.
    bool public pause;

    /// @dev The address of the contract which will receive fees.
    address public rewards;

    /// @dev A mapping of adapter addresses to keep track of vault adapters that have already been added
    mapping(YearnVaultAdapterWithIndirection => bool) public adapters;

    /// @dev A list of all of the vaults. The last element of the list is the vault that is currently being used for
    /// deposits and withdraws. VaultWithIndirections before the last element are considered inactive and are expected to be cleared.
    VaultWithIndirection.List private _vaults;

    /// @dev make sure the contract is only initialized once.
    bool public initialized;

    /// @dev mapping of user account to the last block they acted
    mapping(address => uint256) public lastUserAction;

    /// @dev number of blocks to delay between allowed user actions
    uint256 public minUserActionDelay;

    event GovernanceUpdated(
        address governance
    );

    event PendingGovernanceUpdated(
        address pendingGovernance
    );

    event SentinelUpdated(
        address sentinel
    );

    event TransmuterPeriodUpdated(
        uint256 newTransmutationPeriod
    );

    event TokenClaimed(
        address claimant,
        address token,
        uint256 amountClaimed
    );

    event AlUsdStaked(
        address staker,
        uint256 amountStaked
    );

    event AlUsdUnstaked(
        address staker,
        uint256 amountUnstaked
    );

    event Transmutation(
        address transmutedTo,
        uint256 amountTransmuted
    );

    event ForcedTransmutation(
        address transmutedBy,
        address transmutedTo,
        uint256 amountTransmuted
    );

    event Distribution(
        address origin,
        uint256 amount
    );

    event WhitelistSet(
        address whitelisted,
        bool state
    );

    event KeepersSet(
        address[] keepers,
        bool[] states
    );

    event PlantableThresholdUpdated(
        uint256 plantableThreshold
    );
    
    event PlantableMarginUpdated(
        uint256 plantableMargin
    );

    event MinUserActionDelayUpdated(
        uint256 minUserActionDelay
    );

    event ActiveVaultUpdated(
        YearnVaultAdapterWithIndirection indexed adapter
    );

    event PauseUpdated(
        bool status
    );

    event FundsRecalled(
        uint256 indexed vaultId,
        uint256 withdrawnAmount,
        uint256 decreasedValue
    );

    event FundsHarvested(
        uint256 withdrawnAmount,
        uint256 decreasedValue
    );

    event RewardsUpdated(
        address treasury
    );

    event MigrationComplete(
        address migrateTo,
        uint256 fundsMigrated
    );

    constructor(address _alToken, address _token, address _governance) public {
        require(_governance != ZERO_ADDRESS, "Transmuter: 0 gov");
        governance = _governance;
        alToken = _alToken;
        token = _token;
        transmutationPeriod = 500000;
        minUserActionDelay = 1;
        pause = true;
    }

    ///@return displays the user's share of the pooled alTokens.
    function dividendsOwing(address account) public view returns (uint256) {
        uint256 newDividendPoints = totalDividendPoints.sub(lastDividendPoints[account]);
        return depositedAlTokens[account].mul(newDividendPoints).div(pointMultiplier);
    }

    /// @dev Checks that caller is not a eoa.
    ///
    /// This is used to prevent contracts from interacting.
    modifier noContractAllowed() {
            require(!address(msg.sender).isContract() && msg.sender == tx.origin, "no contract calls");
        _;
    }

    ///@dev modifier to fill the bucket and keep bookkeeping correct incase of increase/decrease in shares
    modifier updateAccount(address account) {
        uint256 owing = dividendsOwing(account);
        if (owing > 0) {
            unclaimedDividends = unclaimedDividends.sub(owing);
            tokensInBucket[account] = tokensInBucket[account].add(owing);
        }
        lastDividendPoints[account] = totalDividendPoints;
        _;
    }
    ///@dev modifier add users to userlist. Users are indexed in order to keep track of when a bond has been filled
    modifier checkIfNewUser() {
        if (!userIsKnown[msg.sender]) {
            userList[nextUser] = msg.sender;
            userIsKnown[msg.sender] = true;
            nextUser++;
        }
        _;
    }

    ///@dev run the phased distribution of the buffered funds
    modifier runPhasedDistribution() {
        uint256 _lastDepositBlock = lastDepositBlock;
        uint256 _currentBlock = block.number;
        uint256 _toDistribute = 0;
        uint256 _buffer = buffer;

        // check if there is something in bufffer
        if (_buffer > 0) {
            // NOTE: if last deposit was updated in the same block as the current call
            // then the below logic gates will fail

            //calculate diffrence in time
            uint256 deltaTime = _currentBlock.sub(_lastDepositBlock);

            // distribute all if bigger than timeframe
            if(deltaTime >= transmutationPeriod) {
                _toDistribute = _buffer;
            } else {

                //needs to be bigger than 0 cuzz solidity no decimals
                if(_buffer.mul(deltaTime) > transmutationPeriod)
                {
                    _toDistribute = _buffer.mul(deltaTime).div(transmutationPeriod);
                }
            }

            // factually allocate if any needs distribution
            if(_toDistribute > 0){

                // remove from buffer
                buffer = _buffer.sub(_toDistribute);

                // increase the allocation
                increaseAllocations(_toDistribute);
            }
        }

        // current timeframe is now the last
        lastDepositBlock = _currentBlock;
        _;
    }

    /// @dev A modifier which checks if whitelisted for minting.
    modifier onlyWhitelisted() {
        require(whiteList[msg.sender], "Transmuter: !whitelisted");
        _;
    }

    /// @dev A modifier which checks if caller is a keepr.
    modifier onlyKeeper() {
        require(keepers[msg.sender], "Transmuter: !keeper");
        _;
    }

    /// @dev Checks that the current message sender or caller is the governance address.
    ///
    ///
    modifier onlyGov() {
        require(msg.sender == governance, "Transmuter: !governance");
        _;
    }

    /// @dev checks that the block delay since a user's last action is longer than the minium delay
    ///
    modifier ensureUserActionDelay() {
        require(block.number.sub(lastUserAction[msg.sender]) >= minUserActionDelay, "action delay not met");
        lastUserAction[msg.sender] = block.number;
        _;
    }

    ///@dev set the transmutationPeriod variable
    ///
    /// sets the length (in blocks) of one full distribution phase
    function setTransmutationPeriod(uint256 newTransmutationPeriod) public onlyGov() {
        transmutationPeriod = newTransmutationPeriod;
        emit TransmuterPeriodUpdated(transmutationPeriod);
    }

    ///@dev claims the base token after it has been transmuted
    ///
    ///This function reverts if there is no realisedToken balance
    function claim(bool asEth) 
        public 
        noContractAllowed() 
    {
        address sender = msg.sender;
        require(realisedTokens[sender] > 0);
        uint256 value = realisedTokens[sender];
        realisedTokens[sender] = 0;
        ensureSufficientFundsExistLocally(value);
        if (asEth) {
            IWETH9(token).withdraw(value);
            payable(sender).transfer(value);
        } else {
            IERC20Burnable(token).safeTransfer(sender, value);
        }
        emit TokenClaimed(sender, token, value);
    }

    ///@dev Withdraws staked alTokens from the transmuter
    ///
    /// This function reverts if you try to draw more tokens than you deposited
    ///
    ///@param amount the amount of alTokens to unstake
    function unstake(uint256 amount) 
        public 
        noContractAllowed() 
        updateAccount(msg.sender) 
    {
        // by calling this function before transmuting you forfeit your gained allocation
        address sender = msg.sender;
        require(depositedAlTokens[sender] >= amount,"Transmuter: unstake amount exceeds deposited amount");
        depositedAlTokens[sender] = depositedAlTokens[sender].sub(amount);
        totalSupplyAltokens = totalSupplyAltokens.sub(amount);
        IERC20Burnable(alToken).safeTransfer(sender, amount);
        emit AlUsdUnstaked(sender, amount);
    }
    ///@dev Deposits alTokens into the transmuter 
    ///
    ///@param amount the amount of alTokens to stake
    function stake(uint256 amount)
        public
        noContractAllowed()
        ensureUserActionDelay()
        runPhasedDistribution()
        updateAccount(msg.sender)
        checkIfNewUser()
    {
        require(!pause, "emergency pause enabled");

        // requires approval of AlToken first
        address sender = msg.sender;
        //require tokens transferred in;
        IERC20Burnable(alToken).safeTransferFrom(sender, address(this), amount);
        totalSupplyAltokens = totalSupplyAltokens.add(amount);
        depositedAlTokens[sender] = depositedAlTokens[sender].add(amount);
        emit AlUsdStaked(sender, amount);
    }
    /// @dev Converts the staked alTokens to the base tokens in amount of the sum of pendingdivs and tokensInBucket
    ///
    /// once the alToken has been converted, it is burned, and the base token becomes realisedTokens which can be recieved using claim()    
    ///
    /// reverts if there are no pendingdivs or tokensInBucket
    function transmute()
        public 
        noContractAllowed() 
        ensureUserActionDelay() 
        runPhasedDistribution() 
        updateAccount(msg.sender) 
    {
        address sender = msg.sender;
        uint256 pendingz = tokensInBucket[sender];
        uint256 diff;

        require(pendingz > 0, "need to have pending in bucket");

        tokensInBucket[sender] = 0;

        // check bucket overflow
        if (pendingz > depositedAlTokens[sender]) {
            diff = pendingz.sub(depositedAlTokens[sender]);

            // remove overflow
            pendingz = depositedAlTokens[sender];
        }

        // decrease altokens
        depositedAlTokens[sender] = depositedAlTokens[sender].sub(pendingz);

        // BURN ALTOKENS
        IERC20Burnable(alToken).burn(pendingz);

        // adjust total
        totalSupplyAltokens = totalSupplyAltokens.sub(pendingz);

        // reallocate overflow
        increaseAllocations(diff);

        // add payout
        realisedTokens[sender] = realisedTokens[sender].add(pendingz);

        emit Transmutation(sender, pendingz);
    }

    /// @dev Executes transmute() on another account that has had more base tokens allocated to it than alTokens staked.
    ///
    /// The caller of this function will have the surlus base tokens credited to their tokensInBucket balance, rewarding them for performing this action
    ///
    /// This function reverts if the address to transmute is not over-filled.
    ///
    /// @param toTransmute address of the account you will force transmute.
    function forceTransmute(address toTransmute)
        public
        noContractAllowed()
        ensureUserActionDelay()
        runPhasedDistribution()
        updateAccount(msg.sender)
        updateAccount(toTransmute)
        checkIfNewUser()
    {
        //load into memory
        uint256 pendingz = tokensInBucket[toTransmute];
        // check restrictions
        require(
            pendingz > depositedAlTokens[toTransmute],
            "Transmuter: !overflow"
        );

        // empty bucket
        tokensInBucket[toTransmute] = 0;

        // calculaate diffrence
        uint256 diff = pendingz.sub(depositedAlTokens[toTransmute]);

        // remove overflow
        pendingz = depositedAlTokens[toTransmute];

        // decrease altokens
        depositedAlTokens[toTransmute] = 0;

        // BURN ALTOKENS
        IERC20Burnable(alToken).burn(pendingz);
        // adjust total
        totalSupplyAltokens = totalSupplyAltokens.sub(pendingz);

        // reallocate overflow
        tokensInBucket[msg.sender] = tokensInBucket[msg.sender].add(diff);

        // add payout
        realisedTokens[toTransmute] = realisedTokens[toTransmute].add(pendingz);

        uint256 value = realisedTokens[toTransmute];

        ensureSufficientFundsExistLocally(value);

        // force payout of realised tokens of the toTransmute address
        realisedTokens[toTransmute] = 0;

        IWETH9(token).withdraw(value);
        payable(toTransmute).transfer(value);

        emit ForcedTransmutation(msg.sender, toTransmute, value);
    }

    /// @dev Transmutes and unstakes all alTokens
    ///
    /// This function combines the transmute and unstake functions for ease of use
    function exit() public noContractAllowed() {
        transmute();
        uint256 toWithdraw = depositedAlTokens[msg.sender];
        unstake(toWithdraw);
    }

    /// @dev Transmutes and claims all converted base tokens.
    ///
    /// This function combines the transmute and claim functions while leaving your remaining alTokens staked.
    function transmuteAndClaim(bool asEth) public noContractAllowed() {
        transmute();
        claim(asEth);
    }

    /// @dev Transmutes, claims base tokens, and withdraws alTokens.
    ///
    /// This function helps users to exit the transmuter contract completely after converting their alTokens to the base pair.
    function transmuteClaimAndWithdraw(bool asEth) public noContractAllowed() {
        transmute();
        claim(asEth);
        uint256 toWithdraw = depositedAlTokens[msg.sender];
        unstake(toWithdraw);
    }

    /// @dev Distributes the base token proportionally to all alToken stakers.
    ///
    /// This function is meant to be called by the Alchemist contract for when it is sending yield to the transmuter. 
    /// Anyone can call this and add funds, idk why they would do that though...
    ///
    /// @param origin the account that is sending the tokens to be distributed.
    /// @param amount the amount of base tokens to be distributed to the transmuter.
    function distribute(address origin, uint256 amount) public onlyWhitelisted() runPhasedDistribution() {
        require(!pause, "emergency pause enabled");
        IERC20Burnable(token).safeTransferFrom(origin, address(this), amount);
        buffer = buffer.add(amount);
        _plantOrRecallExcessFunds();
        emit Distribution(origin, amount);
    }

    /// @dev Allocates the incoming yield proportionally to all alToken stakers.
    ///
    /// @param amount the amount of base tokens to be distributed in the transmuter.
    function increaseAllocations(uint256 amount) internal {
        if(totalSupplyAltokens > 0 && amount > 0) {
            totalDividendPoints = totalDividendPoints.add(
                amount.mul(pointMultiplier).div(totalSupplyAltokens)
            );
            unclaimedDividends = unclaimedDividends.add(amount);
        } else {
            buffer = buffer.add(amount);
        }
    }

    /// @dev Gets the status of a user's staking position.
    ///
    /// The total amount allocated to a user is the sum of pendingdivs and inbucket.
    ///
    /// @param user the address of the user you wish to query.
    ///
    /// returns user status
    
    function userInfo(address user)
        public
        view
        returns (
            uint256 depositedAl,
            uint256 pendingdivs,
            uint256 inbucket,
            uint256 realised
        )
    {
        uint256 _depositedAl = depositedAlTokens[user];
        uint256 _toDistribute = buffer.mul(block.number.sub(lastDepositBlock)).div(transmutationPeriod);
        if(block.number.sub(lastDepositBlock) > transmutationPeriod){
            _toDistribute = buffer;
        }
        uint256 _pendingdivs = _toDistribute.mul(depositedAlTokens[user]).div(totalSupplyAltokens);
        uint256 _inbucket = tokensInBucket[user].add(dividendsOwing(user));
        uint256 _realised = realisedTokens[user];
        return (_depositedAl, _pendingdivs, _inbucket, _realised);
    }

    /// @dev Gets the status of multiple users in one call
    ///
    /// This function is used to query the contract to check for
    /// accounts that have overfilled positions in order to check 
    /// who can be force transmuted.
    ///
    /// @param from the first index of the userList
    /// @param to the last index of the userList
    ///
    /// returns the userList with their staking status in paginated form. 
    function getMultipleUserInfo(uint256 from, uint256 to)
        public
        view
        returns (address[] memory theUserList, uint256[] memory theUserData)
    {
        uint256 i = from;
        uint256 delta = to - from;
        address[] memory _theUserList = new address[](delta); //user
        uint256[] memory _theUserData = new uint256[](delta * 2); //deposited-bucket
        uint256 y = 0;
        uint256 _toDistribute = buffer.mul(block.number.sub(lastDepositBlock)).div(transmutationPeriod);
        if(block.number.sub(lastDepositBlock) > transmutationPeriod){
            _toDistribute = buffer;
        }
        for (uint256 x = 0; x < delta; x += 1) {
            _theUserList[x] = userList[i];
            _theUserData[y] = depositedAlTokens[userList[i]];
            _theUserData[y + 1] = dividendsOwing(userList[i]).add(tokensInBucket[userList[i]]).add(_toDistribute.mul(depositedAlTokens[userList[i]]).div(totalSupplyAltokens));
            y += 2;
            i += 1;
        }
        return (_theUserList, _theUserData);
    }

    /// @dev Gets info on the buffer
    ///
    /// This function is used to query the contract to get the
    /// latest state of the buffer
    ///
    /// @return _toDistribute the amount ready to be distributed
    /// @return _deltaBlocks the amount of time since the last phased distribution
    /// @return _buffer the amount in the buffer 
    function bufferInfo() public view returns (uint256 _toDistribute, uint256 _deltaBlocks, uint256 _buffer){
        _deltaBlocks = block.number.sub(lastDepositBlock);
        _buffer = buffer; 
        _toDistribute = _buffer.mul(_deltaBlocks).div(transmutationPeriod);
    }

    /// @dev Sets the pending governance.
    ///
    /// This function reverts if the new pending governance is the zero address or the caller is not the current
    /// governance. This is to prevent the contract governance being set to the zero address which would deadlock
    /// privileged contract functionality.
    ///
    /// @param _pendingGovernance the new pending governance.
    function setPendingGovernance(address _pendingGovernance) external onlyGov() {
        require(_pendingGovernance != ZERO_ADDRESS, "Transmuter: 0 gov");

        pendingGovernance = _pendingGovernance;

        emit PendingGovernanceUpdated(_pendingGovernance);
    }

    /// @dev Accepts the role as governance.
    ///
    /// This function reverts if the caller is not the new pending governance.
    function acceptGovernance() external  {
        require(msg.sender == pendingGovernance,"!pendingGovernance");
        address _pendingGovernance = pendingGovernance;
        governance = _pendingGovernance;

        emit GovernanceUpdated(_pendingGovernance);
    }

    /// @dev Sets the whitelist
    ///
    /// This function reverts if the caller is not governance
    ///
    /// @param _toWhitelist the address to alter whitelist permissions.
    /// @param _state the whitelist state.
    function setWhitelist(address _toWhitelist, bool _state) external onlyGov() {
        whiteList[_toWhitelist] = _state;
        emit WhitelistSet(_toWhitelist, _state);
    }

    /// @dev Sets the keeper list
    ///
    /// This function reverts if the caller is not governance
    ///
    /// @param _keepers the accounts to set states for.
    /// @param _states the accounts states.
    function setKeepers(address[] calldata _keepers, bool[] calldata _states) external onlyGov() {
        uint256 n = _keepers.length;
        for(uint256 i = 0; i < n; i++) {
            keepers[_keepers[i]] = _states[i];
        }
        emit KeepersSet(_keepers, _states);
    }

    /// @dev Initializes the contract.
    ///
    /// This function checks that the transmuter and rewards have been set and sets up the active vault.
    ///
    /// @param _adapter the vault adapter of the active vault.
    function initialize(YearnVaultAdapterWithIndirection _adapter) external onlyGov {
        require(!initialized, "Transmuter: already initialized");
        require(rewards != ZERO_ADDRESS, "Transmuter: cannot initialize rewards address to 0x0");

        _updateActiveVault(_adapter);

        initialized = true;
    }

    function migrate(YearnVaultAdapterWithIndirection _adapter) external onlyGov() {
        _updateActiveVault(_adapter);
    }

    /// @dev Updates the active vault.
    ///
    /// This function reverts if the vault adapter is the zero address, if the token that the vault adapter accepts
    /// is not the token that this contract defines as the parent asset, or if the contract has not yet been initialized.
    ///
    /// @param _adapter the adapter for the new active vault.
    function _updateActiveVault(YearnVaultAdapterWithIndirection _adapter) internal {
        require(_adapter != YearnVaultAdapterWithIndirection(ZERO_ADDRESS), "Transmuter: active vault address cannot be 0x0.");
        require(address(_adapter.token()) == token, "Transmuter.vault: token mismatch.");
        require(!adapters[_adapter], "Adapter already in use");
        adapters[_adapter] = true;
        _vaults.push(VaultWithIndirection.Data({
            adapter: _adapter,
            totalDeposited: 0
        }));

        emit ActiveVaultUpdated(_adapter);
    }

    /// @dev Gets the number of vaults in the vault list.
    ///
    /// @return the vault count.
    function vaultCount() external view returns (uint256) {
        return _vaults.length();
    }

    /// @dev Get the adapter of a vault.
    ///
    /// @param _vaultId the identifier of the vault.
    ///
    /// @return the vault adapter.
    function getVaultAdapter(uint256 _vaultId) external view returns (address) {
        VaultWithIndirection.Data storage _vault = _vaults.get(_vaultId);
        return address(_vault.adapter);
    }

    /// @dev Get the total amount of the parent asset that has been deposited into a vault.
    ///
    /// @param _vaultId the identifier of the vault.
    ///
    /// @return the total amount of deposited tokens.
    function getVaultTotalDeposited(uint256 _vaultId) external view returns (uint256) {
        VaultWithIndirection.Data storage _vault = _vaults.get(_vaultId);
        return _vault.totalDeposited;
    }


    /// @dev Recalls funds from active vault if less than amt exist locally
    ///
    /// @param amt amount of funds that need to exist locally to fulfill pending request
    function ensureSufficientFundsExistLocally(uint256 amt) internal {
        uint256 currentBal = IERC20Burnable(token).balanceOf(address(this));
        if (currentBal < amt) {
            uint256 diff = amt - currentBal;
            // get enough funds from active vault to replenish local holdings & fulfill claim request
            _recallExcessFundsFromActiveVault(plantableThreshold.add(diff));
        }
    }

    /// @dev Recalls all planted funds from a target vault
    ///
    /// @param _vaultId the id of the vault from which to recall funds
    function recallAllFundsFromVault(uint256 _vaultId) external {
        require(pause && (msg.sender == governance || msg.sender == sentinel), "Transmuter: not paused, or not governance or sentinel");
        _recallAllFundsFromVault(_vaultId);
    }

    /// @dev Recalls all planted funds from a target vault
    ///
    /// @param _vaultId the id of the vault from which to recall funds
    function _recallAllFundsFromVault(uint256 _vaultId) internal {
        VaultWithIndirection.Data storage _vault = _vaults.get(_vaultId);
        (uint256 _withdrawnAmount, uint256 _decreasedValue) = _vault.withdrawAll(address(this));
        emit FundsRecalled(_vaultId, _withdrawnAmount, _decreasedValue);
    }

    /// @dev Recalls planted funds from a target vault
    ///
    /// @param _vaultId the id of the vault from which to recall funds
    /// @param _amount the amount of funds to recall
    function recallFundsFromVault(uint256 _vaultId, uint256 _amount) external {
        require(pause && (msg.sender == governance || msg.sender == sentinel), "Transmuter: not paused, or not governance or sentinel");
        _recallFundsFromVault(_vaultId, _amount);
    }

    /// @dev Recalls planted funds from a target vault
    ///
    /// @param _vaultId the id of the vault from which to recall funds
    /// @param _amount the amount of funds to recall
    function _recallFundsFromVault(uint256 _vaultId, uint256 _amount) internal {
        VaultWithIndirection.Data storage _vault = _vaults.get(_vaultId);
        (uint256 _withdrawnAmount, uint256 _decreasedValue) = _vault.withdraw(address(this), _amount);
        emit FundsRecalled(_vaultId, _withdrawnAmount, _decreasedValue);
    }

    /// @dev Recalls planted funds from the active vault
    ///
    /// @param _amount the amount of funds to recall
    function _recallFundsFromActiveVault(uint256 _amount) internal {
        _recallFundsFromVault(_vaults.lastIndex(), _amount);
    }

    /// @dev Plants or recalls funds from the active vault
    ///
    /// This function plants excess funds in an external vault, or recalls them from the external vault
    /// Should only be called as part of distribute()
    function _plantOrRecallExcessFunds() internal {
        // check if the transmuter holds more funds than plantableThreshold
        uint256 bal = IERC20Burnable(token).balanceOf(address(this));
        uint256 marginVal = plantableThreshold.mul(plantableMargin).div(100);
        if (bal > plantableThreshold.add(marginVal)) {
            uint256 plantAmt = bal - plantableThreshold;
            // if total funds above threshold, send funds to vault
            VaultWithIndirection.Data storage _activeVault = _vaults.last();
            _activeVault.deposit(plantAmt);
        } else if (bal < plantableThreshold.sub(marginVal)) {
            // if total funds below threshold, recall funds from vault
            // first check that there are enough funds in vault
            uint256 harvestAmt = plantableThreshold - bal;
            _recallExcessFundsFromActiveVault(harvestAmt);
        }
    }

    /// @dev Recalls up to the harvestAmt from the active vault
    ///
    /// This function will recall less than harvestAmt if only less is available
    ///
    /// @param _recallAmt the amount to harvest from the active vault
    function _recallExcessFundsFromActiveVault(uint256 _recallAmt) internal {
        VaultWithIndirection.Data storage _activeVault = _vaults.last();
        uint256 activeVaultVal = _activeVault.totalValue();
        if (activeVaultVal < _recallAmt) {
            _recallAmt = activeVaultVal;
        }
        if (_recallAmt > 0) {
            _recallFundsFromActiveVault(_recallAmt);
        }
    }

    /// @dev Sets the address of the sentinel
    ///
    /// @param _sentinel address of the new sentinel
    function setSentinel(address _sentinel) external onlyGov() {
        require(_sentinel != ZERO_ADDRESS, "Transmuter: sentinel address cannot be 0x0.");
        sentinel = _sentinel;
        emit SentinelUpdated(_sentinel);
    }

    /// @dev Sets the threshold of total held funds above which excess funds will be planted in yield farms.
    ///
    /// This function reverts if the caller is not the current governance.
    ///
    /// @param _plantableThreshold the new plantable threshold.
    function setPlantableThreshold(uint256 _plantableThreshold) external onlyGov() {
        plantableThreshold = _plantableThreshold;
        emit PlantableThresholdUpdated(_plantableThreshold);
    }

    /// @dev Sets the plantableThreshold margin for triggering the planting or recalling of funds on harvest
    ///
    /// This function reverts if the caller is not the current governance.
    ///
    /// @param _plantableMargin the new plantable margin.
    function setPlantableMargin(uint256 _plantableMargin) external onlyGov() {
        plantableMargin = _plantableMargin;
        emit PlantableMarginUpdated(_plantableMargin);
    }

    /// @dev Sets the minUserActionDelay 
    ///
    /// This function reverts if the caller is not the current governance.
    ///
    /// @param _minUserActionDelay the new min user action delay.
    function setMinUserActionDelay(uint256 _minUserActionDelay) external onlyGov() {
        minUserActionDelay = _minUserActionDelay;
        emit MinUserActionDelayUpdated(_minUserActionDelay);
    }

    /// @dev Sets if the contract should enter emergency exit mode.
    ///
    /// There are 2 main reasons to pause:
    ///     1. Need to shut down deposits in case of an emergency in one of the vaults
    ///     2. Need to migrate to a new transmuter
    ///
    /// While the transmuter is paused, deposit() and distribute() are disabled
    ///
    /// @param _pause if the contract should enter emergency exit mode.
    function setPause(bool _pause) external {
        require(msg.sender == governance || msg.sender == sentinel, "!(gov || sentinel)");
        pause = _pause;
        emit PauseUpdated(_pause);
    }

    /// @dev Harvests yield from a vault.
    ///
    /// @param _vaultId the identifier of the vault to harvest from.
    ///
    /// @return the amount of funds that were harvested from the vault.
    function harvest(uint256 _vaultId) external onlyKeeper() returns (uint256, uint256) {

        VaultWithIndirection.Data storage _vault = _vaults.get(_vaultId);

        (uint256 _harvestedAmount, uint256 _decreasedValue) = _vault.harvest(rewards);

        emit FundsHarvested(_harvestedAmount, _decreasedValue);

        return (_harvestedAmount, _decreasedValue);
    }

    /// @dev Sets the rewards contract.
    ///
    /// This function reverts if the new rewards contract is the zero address or the caller is not the current governance.
    ///
    /// @param _rewards the new rewards contract.
    function setRewards(address _rewards) external onlyGov() {
        // Check that the rewards address is not the zero address. Setting the rewards to the zero address would break
        // transfers to the address because of `safeTransfer` checks.
        require(_rewards != ZERO_ADDRESS, "Transmuter: rewards address cannot be 0x0.");

        rewards = _rewards;

        emit RewardsUpdated(_rewards);
    }

    /// @dev Migrates transmuter funds to a new transmuter
    ///
    /// @param migrateTo address of the new transmuter
    function migrateFunds(address migrateTo) external onlyGov() {
        require(migrateTo != address(0), "cannot migrate to 0x0");
        require(pause, "migrate: set emergency exit first");

        // leave enough funds to service any pending transmutations
        uint256 totalFunds = IERC20Burnable(token).balanceOf(address(this));
        uint256 migratableFunds = totalFunds.sub(totalSupplyAltokens, "not enough funds to service stakes");
        IERC20Burnable(token).approve(migrateTo, migratableFunds);
        ITransmuter(migrateTo).distribute(address(this), migratableFunds);
        emit MigrationComplete(migrateTo, migratableFunds);
    }

    /// @dev Recover eth sent directly to the Alchemist
    ///
    /// only callable by governance
    function recoverLostFunds() external onlyGov() {
        payable(governance).transfer(address(this).balance);
    }

    receive() external payable {}
}

File 3 of 19 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../utils/Context.sol";

File 4 of 19 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using 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 5 of 19 : SafeMath.sol
// SPDX-License-Identifier: MIT

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, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @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) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @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) {
        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, reverting 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) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * 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);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * 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);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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 6 of 19 : 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);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(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 7 of 19 : IERC20Burnable.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.12;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IERC20Burnable is IERC20 {
  function burn(uint256 amount) external;
  function burnFrom(address account, uint256 amount) external;
}

File 8 of 19 : YearnVaultAdapterWithIndirection.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

import "hardhat/console.sol";

import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol";

import {FixedPointMath} from "../libraries/FixedPointMath.sol";
import {IDetailedERC20} from "../interfaces/IDetailedERC20.sol";
import {IVaultAdapter} from "../interfaces/IVaultAdapter.sol";
import {IyVaultV2} from "../interfaces/IyVaultV2.sol";
import {YearnVaultAdapter} from "./YearnVaultAdapter.sol";

/// @title YearnVaultAdapter
///
/// @dev A vault adapter implementation which wraps a yEarn vault.
contract YearnVaultAdapterWithIndirection is YearnVaultAdapter {
    using FixedPointMath for FixedPointMath.FixedDecimal;
    using SafeERC20 for IDetailedERC20;
    using SafeERC20 for IyVaultV2;
    using SafeMath for uint256;

    constructor(IyVaultV2 _vault, address _admin) YearnVaultAdapter(_vault, _admin) public {
    }

    /// @dev Sends vault tokens to the recipient
    ///
    /// This function reverts if the caller is not the admin.
    ///
    /// @param _recipient the account to send the tokens to.
    /// @param _amount    the amount of tokens to send.
    function indirectWithdraw(address _recipient, uint256 _amount) external onlyAdmin {
        vault.safeTransfer(_recipient, _tokensToShares(_amount));
    }
}

File 9 of 19 : VaultWithIndirection.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.12;

//import "hardhat/console.sol";

import {Math} from "@openzeppelin/contracts/math/Math.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol";
import {IDetailedERC20} from "../../interfaces/IDetailedERC20.sol";
import {YearnVaultAdapterWithIndirection} from "../../adapters/YearnVaultAdapterWithIndirection.sol";
import "hardhat/console.sol";

/// @title Pool
///
/// @dev A library which provides the Vault data struct and associated functions.
library VaultWithIndirection {
  using VaultWithIndirection for Data;
  using VaultWithIndirection for List;
  using SafeERC20 for IDetailedERC20;
  using SafeMath for uint256;

  struct Data {
    YearnVaultAdapterWithIndirection adapter;
    uint256 totalDeposited;
  }

  struct List {
    Data[] elements;
  }

  /// @dev Gets the total amount of assets deposited in the vault.
  ///
  /// @return the total assets.
  function totalValue(Data storage _self) internal view returns (uint256) {
    return _self.adapter.totalValue();
  }

  /// @dev Gets the token that the vault accepts.
  ///
  /// @return the accepted token.
  function token(Data storage _self) internal view returns (IDetailedERC20) {
    return IDetailedERC20(_self.adapter.token());
  }

  /// @dev Deposits funds from the caller into the vault.
  ///
  /// @param _amount the amount of funds to deposit.
  function deposit(Data storage _self, uint256 _amount) internal returns (uint256) {
    // Push the token that the vault accepts onto the stack to save gas.
    IDetailedERC20 _token = _self.token();

    _token.safeTransfer(address(_self.adapter), _amount);
    _self.adapter.deposit(_amount);
    _self.totalDeposited = _self.totalDeposited.add(_amount);

    return _amount;
  }

  /// @dev Deposits the entire token balance of the caller into the vault.
  function depositAll(Data storage _self) internal returns (uint256) {
    IDetailedERC20 _token = _self.token();
    return _self.deposit(_token.balanceOf(address(this)));
  }

  /// @dev Withdraw deposited funds from the vault.
  ///
  /// @param _recipient the account to withdraw the tokens to.
  /// @param _amount    the amount of tokens to withdraw.
  function withdraw(Data storage _self, address _recipient, uint256 _amount) internal returns (uint256, uint256) {
    (uint256 _withdrawnAmount, uint256 _decreasedValue) = _self.directWithdraw(_recipient, _amount);
    _self.totalDeposited = _self.totalDeposited.sub(_decreasedValue);
    return (_withdrawnAmount, _decreasedValue);
  }

  /// @dev Directly withdraw deposited funds from the vault.
  ///
  /// @param _recipient the account to withdraw the tokens to.
  /// @param _amount    the amount of tokens to withdraw.
  function directWithdraw(Data storage _self, address _recipient, uint256 _amount) internal returns (uint256, uint256) {
    IDetailedERC20 _token = _self.token();

    uint256 _startingBalance = _token.balanceOf(_recipient);
    uint256 _startingTotalValue = _self.totalValue();

    _self.adapter.withdraw(_recipient, _amount);

    uint256 _endingBalance = _token.balanceOf(_recipient);
    uint256 _withdrawnAmount = _endingBalance.sub(_startingBalance);

    uint256 _endingTotalValue = _self.totalValue();
    uint256 _decreasedValue = _startingTotalValue.sub(_endingTotalValue);

    return (_withdrawnAmount, _decreasedValue);
  }

  /// @dev Directly withdraw deposited funds from the vault.
  ///
  /// @param _recipient the account to withdraw the tokens to.
  /// @param _amount    the amount of tokens to withdraw.
  function indirectWithdraw(Data storage _self, address _recipient, uint256 _amount) internal returns (uint256, uint256) {
    IDetailedERC20 _token = _self.token();

    uint256 _startingBalance = _token.balanceOf(_recipient);
    uint256 _startingTotalValue = _self.totalValue();

    _self.adapter.indirectWithdraw(_recipient, _amount);

    uint256 _endingBalance = _token.balanceOf(_recipient);
    uint256 _withdrawnAmount = _endingBalance.sub(_startingBalance);

    uint256 _endingTotalValue = _self.totalValue();
    uint256 _decreasedValue = _startingTotalValue.sub(_endingTotalValue);

    return (_withdrawnAmount, _decreasedValue);
  }

  /// @dev Withdraw all the deposited funds from the vault.
  ///
  /// @param _recipient the account to withdraw the tokens to.
  function withdrawAll(Data storage _self, address _recipient) internal returns (uint256, uint256) {
    return _self.withdraw(_recipient, _self.totalDeposited);
  }

  /// @dev Harvests yield from the vault.
  ///
  /// @param _recipient the account to withdraw the harvested yield to.
  function harvest(Data storage _self, address _recipient) internal returns (uint256, uint256) {
    if (_self.totalValue() <= _self.totalDeposited) {
      return (0, 0);
    }
    uint256 _withdrawAmount = _self.totalValue().sub(_self.totalDeposited);
    return _self.indirectWithdraw(_recipient, _withdrawAmount);
  }

  /// @dev Adds a element to the list.
  ///
  /// @param _element the element to add.
  function push(List storage _self, Data memory _element) internal {
    _self.elements.push(_element);
  }

  /// @dev Gets a element from the list.
  ///
  /// @param _index the index in the list.
  ///
  /// @return the element at the specified index.
  function get(List storage _self, uint256 _index) internal view returns (Data storage) {
    return _self.elements[_index];
  }

  /// @dev Gets the last element in the list.
  ///
  /// This function will revert if there are no elements in the list.
  ///
  /// @return the last element in the list.
  function last(List storage _self) internal view returns (Data storage) {
    return _self.elements[_self.lastIndex()];
  }

  /// @dev Gets the index of the last element in the list.
  ///
  /// This function will revert if there are no elements in the list.
  ///
  /// @return the index of the last element.
  function lastIndex(List storage _self) internal view returns (uint256) {
    uint256 _length = _self.length();
    return _length.sub(1, "Vault.List: empty");
  }

  /// @dev Gets the number of elements in the list.
  ///
  /// @return the number of elements.
  function length(List storage _self) internal view returns (uint256) {
    return _self.elements.length;
  }
}

File 10 of 19 : ITransmuter.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.12;

interface ITransmuter  {
  function distribute (address origin, uint256 amount) external;
}

File 11 of 19 : IWETH9.sol
pragma solidity ^0.6.12;

interface IWETH9 {
    event  Approval(address indexed src, address indexed guy, uint wad);
    event  Transfer(address indexed src, address indexed dst, uint wad);
    event  Deposit(address indexed dst, uint wad);
    event  Withdrawal(address indexed src, uint wad);

    function deposit() external payable;
    function withdraw(uint wad) external;
    function totalSupply() external view returns (uint);
    function approve(address guy, uint wad) external returns (bool);
    function transfer(address dst, uint wad) external returns (bool);
    function transferFrom(address src, address dst, uint wad) external returns (bool);
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
    function balanceOf(address guy) external view returns (uint256);
}

File 12 of 19 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 13 of 19 : IERC20.sol
// SPDX-License-Identifier: MIT

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 14 of 19 : console.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;

library console {
	address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);

	function _sendLogPayload(bytes memory payload) private view {
		uint256 payloadLength = payload.length;
		address consoleAddress = CONSOLE_ADDRESS;
		assembly {
			let payloadStart := add(payload, 32)
			let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
		}
	}

	function log() internal view {
		_sendLogPayload(abi.encodeWithSignature("log()"));
	}

	function logInt(int p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
	}

	function logUint(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function logString(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function logBool(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function logAddress(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function logBytes(bytes memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
	}

	function logBytes1(bytes1 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
	}

	function logBytes2(bytes2 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
	}

	function logBytes3(bytes3 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
	}

	function logBytes4(bytes4 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
	}

	function logBytes5(bytes5 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
	}

	function logBytes6(bytes6 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
	}

	function logBytes7(bytes7 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
	}

	function logBytes8(bytes8 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
	}

	function logBytes9(bytes9 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
	}

	function logBytes10(bytes10 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
	}

	function logBytes11(bytes11 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
	}

	function logBytes12(bytes12 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
	}

	function logBytes13(bytes13 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
	}

	function logBytes14(bytes14 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
	}

	function logBytes15(bytes15 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
	}

	function logBytes16(bytes16 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
	}

	function logBytes17(bytes17 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
	}

	function logBytes18(bytes18 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
	}

	function logBytes19(bytes19 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
	}

	function logBytes20(bytes20 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
	}

	function logBytes21(bytes21 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
	}

	function logBytes22(bytes22 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
	}

	function logBytes23(bytes23 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
	}

	function logBytes24(bytes24 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
	}

	function logBytes25(bytes25 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
	}

	function logBytes26(bytes26 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
	}

	function logBytes27(bytes27 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
	}

	function logBytes28(bytes28 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
	}

	function logBytes29(bytes29 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
	}

	function logBytes30(bytes30 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
	}

	function logBytes31(bytes31 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
	}

	function logBytes32(bytes32 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
	}

	function log(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function log(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function log(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function log(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function log(uint p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
	}

	function log(uint p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
	}

	function log(uint p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
	}

	function log(uint p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
	}

	function log(string memory p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
	}

	function log(string memory p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
	}

	function log(string memory p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
	}

	function log(string memory p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
	}

	function log(bool p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
	}

	function log(bool p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
	}

	function log(bool p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
	}

	function log(bool p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
	}

	function log(address p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
	}

	function log(address p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
	}

	function log(address p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
	}

	function log(address p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
	}

	function log(uint p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
	}

	function log(uint p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
	}

	function log(uint p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
	}

	function log(uint p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
	}

	function log(uint p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
	}

	function log(uint p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
	}

	function log(uint p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
	}

	function log(uint p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
	}

	function log(uint p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
	}

	function log(uint p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
	}

	function log(uint p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
	}

	function log(uint p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
	}

	function log(string memory p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
	}

	function log(string memory p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
	}

	function log(string memory p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
	}

	function log(string memory p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
	}

	function log(bool p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
	}

	function log(bool p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
	}

	function log(bool p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
	}

	function log(bool p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
	}

	function log(bool p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
	}

	function log(bool p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
	}

	function log(bool p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
	}

	function log(bool p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
	}

	function log(bool p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
	}

	function log(bool p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
	}

	function log(bool p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
	}

	function log(bool p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
	}

	function log(address p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
	}

	function log(address p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
	}

	function log(address p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
	}

	function log(address p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
	}

	function log(address p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
	}

	function log(address p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
	}

	function log(address p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
	}

	function log(address p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
	}

	function log(address p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
	}

	function log(address p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
	}

	function log(address p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
	}

	function log(address p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
	}

	function log(address p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
	}

	function log(address p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
	}

	function log(address p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
	}

	function log(address p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
	}

	function log(uint p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
	}

}

File 15 of 19 : FixedPointMath.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.12;

library FixedPointMath {
  uint256 public constant DECIMALS = 18;
  uint256 public constant SCALAR = 10**DECIMALS;

  struct FixedDecimal {
    uint256 x;
  }

  function fromU256(uint256 value) internal pure returns (FixedDecimal memory) {
    uint256 x;
    require(value == 0 || (x = value * SCALAR) / SCALAR == value);
    return FixedDecimal(x);
  }

  function maximumValue() internal pure returns (FixedDecimal memory) {
    return FixedDecimal(uint256(-1));
  }

  function add(FixedDecimal memory self, FixedDecimal memory value) internal pure returns (FixedDecimal memory) {
    uint256 x;
    require((x = self.x + value.x) >= self.x);
    return FixedDecimal(x);
  }

  function add(FixedDecimal memory self, uint256 value) internal pure returns (FixedDecimal memory) {
    return add(self, fromU256(value));
  }

  function sub(FixedDecimal memory self, FixedDecimal memory value) internal pure returns (FixedDecimal memory) {
    uint256 x;
    require((x = self.x - value.x) <= self.x);
    return FixedDecimal(x);
  }

  function sub(FixedDecimal memory self, uint256 value) internal pure returns (FixedDecimal memory) {
    return sub(self, fromU256(value));
  }

  function mul(FixedDecimal memory self, uint256 value) internal pure returns (FixedDecimal memory) {
    uint256 x;
    require(value == 0 || (x = self.x * value) / value == self.x);
    return FixedDecimal(x);
  }

  function div(FixedDecimal memory self, uint256 value) internal pure returns (FixedDecimal memory) {
    require(value != 0);
    return FixedDecimal(self.x / value);
  }

  function cmp(FixedDecimal memory self, FixedDecimal memory value) internal pure returns (int256) {
    if (self.x < value.x) {
      return -1;
    }

    if (self.x > value.x) {
      return 1;
    }

    return 0;
  }

  function decode(FixedDecimal memory self) internal pure returns (uint256) {
    return self.x / SCALAR;
  }
}

File 16 of 19 : IDetailedERC20.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.12;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IDetailedERC20 is IERC20 {
  function name() external returns (string memory);
  function symbol() external returns (string memory);
  function decimals() external returns (uint8);
}

File 17 of 19 : IVaultAdapter.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.12;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "./IDetailedERC20.sol";

/// Interface for all Vault Adapter implementations.
interface IVaultAdapter {

  /// @dev Gets the token that the adapter accepts.
  function token() external view returns (IDetailedERC20);

  /// @dev The total value of the assets deposited into the vault.
  function totalValue() external view returns (uint256);

  /// @dev Deposits funds into the vault.
  ///
  /// @param _amount  the amount of funds to deposit.
  function deposit(uint256 _amount) external;

  /// @dev Attempts to withdraw funds from the wrapped vault.
  ///
  /// The amount withdrawn to the recipient may be less than the amount requested.
  ///
  /// @param _recipient the recipient of the funds.
  /// @param _amount    the amount of funds to withdraw.
  function withdraw(address _recipient, uint256 _amount) external;
}

File 18 of 19 : IyVaultV2.sol
pragma solidity ^0.6.12;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IyVaultV2 is IERC20 {
    function token() external view returns (address);
    function deposit() external returns (uint);
    function deposit(uint) external returns (uint);
    function deposit(uint, address) external returns (uint);
    function withdraw() external returns (uint);
    function withdraw(uint) external returns (uint);
    function withdraw(uint, address) external returns (uint);
    function withdraw(uint, address, uint) external returns (uint);
    function permit(address, address, uint, uint, bytes32) external view returns (bool);
    function pricePerShare() external view returns (uint);
    
    function apiVersion() external view returns (string memory);
    function totalAssets() external view returns (uint);
    function maxAvailableShares() external view returns (uint);
    function debtOutstanding() external view returns (uint);
    function debtOutstanding(address strategy) external view returns (uint);
    function creditAvailable() external view returns (uint);
    function creditAvailable(address strategy) external view returns (uint);
    function availableDepositLimit() external view returns (uint);
    function expectedReturn() external view returns (uint);
    function expectedReturn(address strategy) external view returns (uint);
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint);
    function balanceOf(address owner) external view override returns (uint);
    function totalSupply() external view override returns (uint);
    function governance() external view returns (address);
    function management() external view returns (address);
    function guardian() external view returns (address);
    function guestList() external view returns (address);
    function strategies(address) external view returns (uint, uint, uint, uint, uint, uint, uint, uint);
    function withdrawalQueue(uint) external view returns (address);
    function emergencyShutdown() external view returns (bool);
    function depositLimit() external view returns (uint);
    function debtRatio() external view returns (uint);
    function totalDebt() external view returns (uint);
    function lastReport() external view returns (uint);
    function activation() external view returns (uint);
    function rewards() external view returns (address);
    function managementFee() external view returns (uint);
    function performanceFee() external view returns (uint);
}

File 19 of 19 : YearnVaultAdapter.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

import "hardhat/console.sol";

import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol";

import {FixedPointMath} from "../libraries/FixedPointMath.sol";
import {IDetailedERC20} from "../interfaces/IDetailedERC20.sol";
import {IVaultAdapter} from "../interfaces/IVaultAdapter.sol";
import {IyVaultV2} from "../interfaces/IyVaultV2.sol";

/// @title YearnVaultAdapter
///
/// @dev A vault adapter implementation which wraps a yEarn vault.
contract YearnVaultAdapter is IVaultAdapter {
  using FixedPointMath for FixedPointMath.FixedDecimal;
  using SafeERC20 for IDetailedERC20;
  using SafeMath for uint256;

  /// @dev The vault that the adapter is wrapping.
  IyVaultV2 public vault;

  /// @dev The address which has admin control over this contract.
  address public admin;

  /// @dev The decimals of the token.
  uint256 public decimals;

  constructor(IyVaultV2 _vault, address _admin) public {
    vault = _vault;
    admin = _admin;
    updateApproval();
    decimals = _vault.decimals();
  }

  /// @dev A modifier which reverts if the caller is not the admin.
  modifier onlyAdmin() {
    require(admin == msg.sender, "YearnVaultAdapter: only admin");
    _;
  }

  /// @dev Gets the token that the vault accepts.
  ///
  /// @return the accepted token.
  function token() external view override returns (IDetailedERC20) {
    return IDetailedERC20(vault.token());
  }

  /// @dev Gets the total value of the assets that the adapter holds in the vault.
  ///
  /// @return the total assets.
  function totalValue() external view override returns (uint256) {
    return _sharesToTokens(vault.balanceOf(address(this)));
  }

  /// @dev Deposits tokens into the vault.
  ///
  /// @param _amount the amount of tokens to deposit into the vault.
  function deposit(uint256 _amount) external override {
    vault.deposit(_amount);
  }

  /// @dev Withdraws tokens from the vault to the recipient.
  ///
  /// This function reverts if the caller is not the admin.
  ///
  /// @param _recipient the account to withdraw the tokes to.
  /// @param _amount    the amount of tokens to withdraw.
  function withdraw(address _recipient, uint256 _amount) external override onlyAdmin {
    vault.withdraw(_tokensToShares(_amount),_recipient);
  }

  /// @dev Updates the vaults approval of the token to be the maximum value.
  function updateApproval() public {
    address _token = vault.token();
    IDetailedERC20(_token).safeApprove(address(vault), uint256(-1));
  }

  /// @dev Computes the number of tokens an amount of shares is worth.
  ///
  /// @param _sharesAmount the amount of shares.
  ///
  /// @return the number of tokens the shares are worth.
  
  function _sharesToTokens(uint256 _sharesAmount) internal view returns (uint256) {
    return _sharesAmount.mul(vault.pricePerShare()).div(10**decimals);
  }

  /// @dev Computes the number of shares an amount of tokens is worth.
  ///
  /// @param _tokensAmount the amount of shares.
  ///
  /// @return the number of shares the tokens are worth.
  function _tokensToShares(uint256 _tokensAmount) internal view returns (uint256) {
    return _tokensAmount.mul(10**decimals).div(vault.pricePerShare());
  }
}

File 20 of 19 : Math.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 999999
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_alToken","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_governance","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract YearnVaultAdapterWithIndirection","name":"adapter","type":"address"}],"name":"ActiveVaultUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountStaked","type":"uint256"}],"name":"AlUsdStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountUnstaked","type":"uint256"}],"name":"AlUsdUnstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"origin","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Distribution","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"transmutedBy","type":"address"},{"indexed":false,"internalType":"address","name":"transmutedTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountTransmuted","type":"uint256"}],"name":"ForcedTransmutation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"withdrawnAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"decreasedValue","type":"uint256"}],"name":"FundsHarvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawnAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"decreasedValue","type":"uint256"}],"name":"FundsRecalled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governance","type":"address"}],"name":"GovernanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"keepers","type":"address[]"},{"indexed":false,"internalType":"bool[]","name":"states","type":"bool[]"}],"name":"KeepersSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"migrateTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"fundsMigrated","type":"uint256"}],"name":"MigrationComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minUserActionDelay","type":"uint256"}],"name":"MinUserActionDelayUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"PauseUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pendingGovernance","type":"address"}],"name":"PendingGovernanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"plantableMargin","type":"uint256"}],"name":"PlantableMarginUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"plantableThreshold","type":"uint256"}],"name":"PlantableThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"treasury","type":"address"}],"name":"RewardsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sentinel","type":"address"}],"name":"SentinelUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"claimant","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountClaimed","type":"uint256"}],"name":"TokenClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"transmutedTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountTransmuted","type":"uint256"}],"name":"Transmutation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTransmutationPeriod","type":"uint256"}],"name":"TransmuterPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"whitelisted","type":"address"},{"indexed":false,"internalType":"bool","name":"state","type":"bool"}],"name":"WhitelistSet","type":"event"},{"inputs":[],"name":"ZERO_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract YearnVaultAdapterWithIndirection","name":"","type":"address"}],"name":"adapters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"alToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bufferInfo","outputs":[{"internalType":"uint256","name":"_toDistribute","type":"uint256"},{"internalType":"uint256","name":"_deltaBlocks","type":"uint256"},{"internalType":"uint256","name":"_buffer","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"asEth","type":"bool"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"depositedAlTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"origin","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"dividendsOwing","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"toTransmute","type":"address"}],"name":"forceTransmute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"}],"name":"getMultipleUserInfo","outputs":[{"internalType":"address[]","name":"theUserList","type":"address[]"},{"internalType":"uint256[]","name":"theUserData","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"getVaultAdapter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"getVaultTotalDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"harvest","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract YearnVaultAdapterWithIndirection","name":"_adapter","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"keepers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastDepositBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastDividendPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastUserAction","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract YearnVaultAdapterWithIndirection","name":"_adapter","type":"address"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"migrateTo","type":"address"}],"name":"migrateFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minUserActionDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingGovernance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"plantableMargin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"plantableThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pointMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"realisedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"recallAllFundsFromVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recallFundsFromVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverLostFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sentinel","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_keepers","type":"address[]"},{"internalType":"bool[]","name":"_states","type":"bool[]"}],"name":"setKeepers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minUserActionDelay","type":"uint256"}],"name":"setMinUserActionDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_pause","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pendingGovernance","type":"address"}],"name":"setPendingGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_plantableMargin","type":"uint256"}],"name":"setPlantableMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_plantableThreshold","type":"uint256"}],"name":"setPlantableThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewards","type":"address"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sentinel","type":"address"}],"name":"setSentinel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newTransmutationPeriod","type":"uint256"}],"name":"setTransmutationPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_toWhitelist","type":"address"},{"internalType":"bool","name":"_state","type":"bool"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokensInBucket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDividendPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyAltokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transmutationPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transmute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"asEth","type":"bool"}],"name":"transmuteAndClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"asEth","type":"bool"}],"name":"transmuteClaimAndWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unclaimedDividends","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"depositedAl","type":"uint256"},{"internalType":"uint256","name":"pendingdivs","type":"uint256"},{"internalType":"uint256","name":"inbucket","type":"uint256"},{"internalType":"uint256","name":"realised","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userIsKnown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"userList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whiteList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6080604052678ac7230489e80000600d556802b5e3af16b188000060125560056013553480156200002f57600080fd5b5060405162005bd738038062005bd7833981810160405260608110156200005557600080fd5b50805160208201516040909201519091906001600160a01b038116620000b6576040805162461bcd60e51b81526020600482015260116024820152702a3930b739b6baba32b91d10181033b7bb60791b604482015290519081900360640190fd5b601480546001600160a01b039283166001600160a01b03199182161790915560018054948316948216949094178455600280549390921692169190911790556207a120600055601c556016805460ff60a01b1916600160a01b179055615ab580620001226000396000f3fe6080604052600436106103c75760003560e01c80638391e45c116101f2578063c2a88e1d1161010d578063ec38a862116100a0578063f58c251c1161006f578063f58c251c14610f47578063f93f394c14610f5c578063fb93210814610f9c578063fc0c546a14610fe2576103ce565b8063ec38a86214610ec8578063edaafe2014610f08578063f1f7920014610f1d578063f39c38a014610f32576103ce565b8063d42c11e1116100dc578063d42c11e114610e1b578063ddc6326214610e30578063e5711ffc14610e73578063e9fad8ee14610eb3576103ce565b8063c2a88e1d14610d45578063c4d66de814610d71578063ce5494bb14610db1578063d2c2949214610df1576103ce565b8063a694fc3a11610185578063b870d59811610154578063b870d59814610c59578063bedb86fb14610c99578063bf51929f14610cc5578063bff170b914610d05576103ce565b8063a694fc3a14610bb0578063a704e8ad14610bda578063a7c6a10014610c1a578063aaf1666014610c2f576103ce565b80639f4216e8116101c15780639f4216e814610b32578063a02fbe2d14610b5c578063a196cf2e14610b86578063a59d698614610b9b576103ce565b80638391e45c14610a9e5780638456cb5914610ade57806394ff119914610af35780639ec5a89414610b1d576103ce565b8063372c12b1116102e2578063658b98a91161027557806378e1270e1161024457806378e1270e146109dd57806379070a1214610a09578063806985f714610a4957806381ac45fb14610a89576103ce565b8063658b98a9146108b45780636790fab3146108c95780636a4f4b05146108de57806370460eb1146109ad576103ce565b806352710007116102b15780635271000714610802578063538ba4f91461084257806353d6fd59146108575780635aa6e6751461089f576103ce565b8063372c12b1146107585780633bbd64bc146107985780633cb802b9146107d85780634bf04bd1146107ed576103ce565b80631acce0301161035a5780632670fdd8116103295780632670fdd81461069a5780632a3d7c81146106ed5780632d81a78e146107025780632e17de781461072e576103ce565b80631acce030146106345780631aeb19861461065b5780632113342d14610670578063238efcbc14610685576103ce565b80630abb6035116103965780630abb60351461053b5780631486bf6e1461057b578063158ef93e146105a55780631959a002146105ce576103ce565b806303036290146103d357806305d2301d1461049c5780630668911e146104cf57806309dac061146104fb576103ce565b366103ce57005b600080fd5b3480156103df57600080fd5b50610403600480360360408110156103f657600080fd5b5080359060200135610ff7565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561044757818101518382015260200161042f565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561048657818101518382015260200161046e565b5050505090500194505050505060405180910390f35b3480156104a857600080fd5b506104b1611254565b60408051938452602084019290925282820152519081900360600190f35b3480156104db57600080fd5b506104f9600480360360208110156104f257600080fd5b503561128e565b005b34801561050757600080fd5b506104f96004803603602081101561051e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661134f565b34801561054757600080fd5b506104f96004803603602081101561055e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166114ba565b34801561058757600080fd5b506104f96004803603602081101561059e57600080fd5b503561163b565b3480156105b157600080fd5b506105ba6116fc565b604080519115158252519081900360200190f35b3480156105da57600080fd5b5061060e600480360360208110156105f157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611705565b604080519485526020850193909352838301919091526060830152519081900360800190f35b34801561064057600080fd5b5061064961181e565b60408051918252519081900360200190f35b34801561066757600080fd5b50610649611824565b34801561067c57600080fd5b5061064961182a565b34801561069157600080fd5b506104f9611830565b3480156106a657600080fd5b506106c4600480360360208110156106bd57600080fd5b5035611932565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156106f957600080fd5b5061064961195e565b34801561070e57600080fd5b506104f96004803603602081101561072557600080fd5b50351515611964565b34801561073a57600080fd5b506104f96004803603602081101561075157600080fd5b5035611b8d565b34801561076457600080fd5b506105ba6004803603602081101561077b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611dfd565b3480156107a457600080fd5b506105ba600480360360208110156107bb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611e12565b3480156107e457600080fd5b50610649611e27565b3480156107f957600080fd5b50610649611e2d565b34801561080e57600080fd5b506106496004803603602081101561082557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611e33565b34801561084e57600080fd5b506106c4611e45565b34801561086357600080fd5b506104f96004803603604081101561087a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001351515611e4a565b3480156108ab57600080fd5b506106c4611f5f565b3480156108c057600080fd5b50610649611f7b565b3480156108d557600080fd5b506106c4611f81565b3480156108ea57600080fd5b506104f96004803603604081101561090157600080fd5b81019060208101813564010000000081111561091c57600080fd5b82018360208201111561092e57600080fd5b8035906020019184602083028401116401000000008311171561095057600080fd5b91939092909160208101903564010000000081111561096e57600080fd5b82018360208201111561098057600080fd5b803590602001918460208302840111640100000000831117156109a257600080fd5b509092509050611f9d565b3480156109b957600080fd5b506104f9600480360360408110156109d057600080fd5b508035906020013561218f565b3480156109e957600080fd5b506104f960048036036020811015610a0057600080fd5b50351515612254565b348015610a1557600080fd5b506105ba60048036036020811015610a2c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166122e8565b348015610a5557600080fd5b5061064960048036036020811015610a6c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166122fd565b348015610a9557600080fd5b5061064961230f565b348015610aaa57600080fd5b5061064960048036036020811015610ac157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612315565b348015610aea57600080fd5b506105ba61238b565b348015610aff57600080fd5b506104f960048036036020811015610b1657600080fd5b50356123ac565b348015610b2957600080fd5b506106c461246d565b348015610b3e57600080fd5b506106c460048036036020811015610b5557600080fd5b5035612489565b348015610b6857600080fd5b506104f960048036036020811015610b7f57600080fd5b50356124b1565b348015610b9257600080fd5b50610649612572565b348015610ba757600080fd5b506104f9612578565b348015610bbc57600080fd5b506104f960048036036020811015610bd357600080fd5b5035612644565b348015610be657600080fd5b5061064960048036036020811015610bfd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612a70565b348015610c2657600080fd5b50610649612a82565b348015610c3b57600080fd5b5061064960048036036020811015610c5257600080fd5b5035612a93565b348015610c6557600080fd5b5061064960048036036020811015610c7c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612aac565b348015610ca557600080fd5b506104f960048036036020811015610cbc57600080fd5b50351515612abe565b348015610cd157600080fd5b506104f960048036036020811015610ce857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612be5565b348015610d1157600080fd5b506104f960048036036020811015610d2857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612fb8565b348015610d5157600080fd5b506104f960048036036020811015610d6857600080fd5b50351515613687565b348015610d7d57600080fd5b506104f960048036036020811015610d9457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613731565b348015610dbd57600080fd5b506104f960048036036020811015610dd457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166138ce565b348015610dfd57600080fd5b506104f960048036036020811015610e1457600080fd5b503561395d565b348015610e2757600080fd5b50610649613a1d565b348015610e3c57600080fd5b50610e5a60048036036020811015610e5357600080fd5b5035613a23565b6040805192835260208301919091528051918290030190f35b348015610e7f57600080fd5b506105ba60048036036020811015610e9657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613b26565b348015610ebf57600080fd5b506104f9613b3b565b348015610ed457600080fd5b506104f960048036036020811015610eeb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613bdc565b348015610f1457600080fd5b50610649613d47565b348015610f2957600080fd5b506104f9613d4d565b348015610f3e57600080fd5b506106c4614221565b348015610f5357600080fd5b506106c461423d565b348015610f6857600080fd5b5061064960048036036020811015610f7f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614259565b348015610fa857600080fd5b506104f960048036036040811015610fbf57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561426b565b348015610fee57600080fd5b506106c4614483565b60608083808403828167ffffffffffffffff8111801561101657600080fd5b50604051908082528060200260200182016040528015611040578160200160208202803683370190505b50905060608260020267ffffffffffffffff8111801561105f57600080fd5b50604051908082528060200260200182016040528015611089578160200160208202803683370190505b5090506000806110bc6000546110b66110ad600c544361449f90919063ffffffff16565b600b549061451b565b9061458e565b90506000546110d6600c544361449f90919063ffffffff16565b11156110e15750600b545b60005b8581101561124157600087815260086020526040902054855173ffffffffffffffffffffffffffffffffffffffff9091169086908390811061112257fe5b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152600089815260088252604080822054909316815260039091522054845185908590811061117257fe5b602090810291909101810191909152600a5460008981526008835260408082205473ffffffffffffffffffffffffffffffffffffffff16825260039093529190912054611214916111c8916110b690869061451b565b60008981526008602081815260408084205473ffffffffffffffffffffffffffffffffffffffff168085526004835290842054938d905291905261120e91908290612315565b9061460f565b84846001018151811061122357fe5b602090810291909101015260019687019660029390930192016110e4565b50929650909450505050505b9250929050565b600080600061126e600c544361449f90919063ffffffff16565b600b546000549193509150611287906110b6838561451b565b9250909192565b60145473ffffffffffffffffffffffffffffffffffffffff16331461131457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b60128190556040805182815290517fe77487d7758cc0f4820329f0d13f96448757377d4bf03ca31ce49cc9e151486f9181900360200190a150565b60145473ffffffffffffffffffffffffffffffffffffffff1633146113d557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116611441576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615a55602b913960400191505060405180910390fd5b6016805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517fdc117600f93282860144d2cd2745f8e2e15c3ca2a32b4290c30f7cd1ae7ffcb99181900360200190a150565b60145473ffffffffffffffffffffffffffffffffffffffff16331461154057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166115c257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f5472616e736d757465723a203020676f76000000000000000000000000000000604482015290519081900360640190fd5b6015805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517fc9e2377236eab4280090ce8f2317332649736d92f00dcf20a8dd6684ec5e78399181900360200190a150565b60145473ffffffffffffffffffffffffffffffffffffffff1633146116c157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b601c8190556040805182815290517f3bff5293be89c925015798c1dfc042b8a1108bad4eb02ba603aea7ed96ac0cfd9181900360200190a150565b601a5460ff1681565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260408120548154600c54839283928392839161174b916110b6906110ad90439061449f565b9050600054611765600c544361449f90919063ffffffff16565b11156117705750600b545b600a5473ffffffffffffffffffffffffffffffffffffffff881660009081526003602052604081205490916117aa916110b690859061451b565b905060006117e66117ba8a612315565b73ffffffffffffffffffffffffffffffffffffffff8b166000908152600460205260409020549061460f565b73ffffffffffffffffffffffffffffffffffffffff999099166000908152600560205260409020549399919897509295509350505050565b60135481565b60125481565b600e5481565b60155473ffffffffffffffffffffffffffffffffffffffff1633146118b657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f2170656e64696e67476f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b601554601480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040805182815290517f9d3e522e1e47a2f6009739342b9cc7b252a1888154e843ab55ee1c81745795ab9181900360200190a150565b600080611940601984614683565b5473ffffffffffffffffffffffffffffffffffffffff169392505050565b600c5481565b61196d336146aa565b15801561197957503332145b6119e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b336000818152600560205260409020546119fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604081208054919055611a30816146b0565b8215611b0a57600254604080517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815260048101849052905173ffffffffffffffffffffffffffffffffffffffff90921691632e1a7d4d9160248082019260009290919082900301818387803b158015611aa957600080fd5b505af1158015611abd573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff8516925083156108fc02915083906000818181858888f19350505050158015611b04573d6000803e3d6000fd5b50611b2e565b600254611b2e9073ffffffffffffffffffffffffffffffffffffffff168383614776565b6002546040805173ffffffffffffffffffffffffffffffffffffffff80861682529092166020830152818101839052517f4831bdd9dcf3048a28319ce81d3cab7a15366bcf449bc7803a539107440809cc9181900360600190a1505050565b611b96336146aa565b158015611ba257503332145b611c0d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b336000611c1982612315565b90508015611c8857600f54611c2e908261449f565b600f5573ffffffffffffffffffffffffffffffffffffffff8216600090815260046020526040902054611c61908261460f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460205260409020555b600e5473ffffffffffffffffffffffffffffffffffffffff831660009081526006602090815260408083209390935533808352600390915291902054841115611d1c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806159746033913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054611d4c908561449f565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260036020526040902055600a54611d7f908561449f565b600a55600154611da69073ffffffffffffffffffffffffffffffffffffffff168286614776565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905281517f51c9b122c2b81c914282042bf02d3a8965f5a0b1ad37b6dab1cb77bb343ce556929181900390910190a150505050565b60106020526000908152604090205460ff1681565b60116020526000908152604090205460ff1681565b600f5481565b600a5481565b60056020526000908152604090205481565b600081565b60145473ffffffffffffffffffffffffffffffffffffffff163314611ed057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526010602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915582519384529083015280517f0aa5ec5ffdc7f6f9c4d0dded489d7450297155cb2f71cb771e02427f7dff4f519281900390910190a15050565b60145473ffffffffffffffffffffffffffffffffffffffff1681565b600d5481565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60145473ffffffffffffffffffffffffffffffffffffffff16331461202357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b8260005b818110156120b85783838281811061203b57fe5b9050602002013515156011600088888581811061205457fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101612027565b507fd1721b10ac5fe95d2627d512aa0f92c34ada0347c874adf414cf51af5760ff56858585856040518080602001806020018381038352878782818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018481038352858152602090810191508690860280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039850909650505050505050a15050505050565b60165474010000000000000000000000000000000000000000900460ff1680156121f1575060145473ffffffffffffffffffffffffffffffffffffffff163314806121f1575060165473ffffffffffffffffffffffffffffffffffffffff1633145b612246576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061588b6035913960400191505060405180910390fd5b6122508282614803565b5050565b61225d336146aa565b15801561226957503332145b6122d457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b6122dc613d4d565b6122e581611964565b50565b60076020526000908152604090205460ff1681565b60066020526000908152604090205481565b60005481565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260066020526040812054600e54829161234a919061449f565b600d5473ffffffffffffffffffffffffffffffffffffffff8516600090815260036020526040902054919250612384916110b6908461451b565b9392505050565b60165474010000000000000000000000000000000000000000900460ff1681565b60145473ffffffffffffffffffffffffffffffffffffffff16331461243257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b60138190556040805182815290517fcf837c6f8ba9f94fb0b21939d04aba4ae1cf50cbeca85513c218dfdc6666f1a99181900360200190a150565b60175473ffffffffffffffffffffffffffffffffffffffff1681565b60086020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60145473ffffffffffffffffffffffffffffffffffffffff16331461253757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b60008190556040805182815290517fc2965d898897107f6f1d0e43c043ca07b7a51d487acfac1decec2ec8405364409181900360200190a150565b60095481565b60145473ffffffffffffffffffffffffffffffffffffffff1633146125fe57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b60145460405173ffffffffffffffffffffffffffffffffffffffff909116904780156108fc02916000818181858888f193505050501580156122e5573d6000803e3d6000fd5b61264d336146aa565b15801561265957503332145b6126c457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b601c54336000908152601b60205260409020546126e290439061449f565b101561274f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f616374696f6e2064656c6179206e6f74206d6574000000000000000000000000604482015290519081900360640190fd5b336000908152601b602052604081204390819055600c54600b5490929080156127d657600061277e848661449f565b90506000548110612791578192506127b8565b60005461279e838361451b565b11156127b8576000546127b5906110b6848461451b565b92505b82156127d4576127c8828461449f565b600b556127d48361486b565b505b600c8390553360006127e782612315565b9050801561285657600f546127fc908261449f565b600f5573ffffffffffffffffffffffffffffffffffffffff821660009081526004602052604090205461282f908261460f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460205260409020555b600e5473ffffffffffffffffffffffffffffffffffffffff831660009081526006602090815260408083209390935533825260079052205460ff166129105760098054600090815260086020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915583526007909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915581540190555b60165474010000000000000000000000000000000000000000900460ff161561299a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f656d657267656e637920706175736520656e61626c6564000000000000000000604482015290519081900360640190fd5b60015433906129c19073ffffffffffffffffffffffffffffffffffffffff1682308b6148d4565b600a546129ce908961460f565b600a5573ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054612a01908961460f565b73ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040918290209390935580519182529181018a905281517fd2c11ddc796e75881f492256edb3cb3bf4c7a7761682320c5798a8dbb3662d88929181900390910190a15050505050505050565b601b6020526000908152604090205481565b6000612a8e601961496f565b905090565b600080612aa1601984614683565b600101549392505050565b60046020526000908152604090205481565b60145473ffffffffffffffffffffffffffffffffffffffff16331480612afb575060165473ffffffffffffffffffffffffffffffffffffffff1633145b612b6657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f2128676f76207c7c2073656e74696e656c290000000000000000000000000000604482015290519081900360640190fd5b601680548215157401000000000000000000000000000000000000000081027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9092169190911790915560408051918252517f77860e247ab9186dbe64e5bd0e0b93273cc4273e01818420e788f500078886f59181900360200190a150565b60145473ffffffffffffffffffffffffffffffffffffffff163314612c6b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116612ced57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f63616e6e6f74206d69677261746520746f203078300000000000000000000000604482015290519081900360640190fd5b60165474010000000000000000000000000000000000000000900460ff16612d60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806159a76021913960400191505060405180910390fd5b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b158015612dd157600080fd5b505afa158015612de5573d6000803e3d6000fd5b505050506040513d6020811015612dfb57600080fd5b5051600a5460408051606081019091526022808252929350600092612e2c9291906158c06020830139849190614973565b600254604080517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260248201859052915193945091169163095ea7b3916044808201926020929091908290030181600087803b158015612eaa57600080fd5b505af1158015612ebe573d6000803e3d6000fd5b505050506040513d6020811015612ed457600080fd5b5050604080517ffb93210800000000000000000000000000000000000000000000000000000000815230600482015260248101839052905173ffffffffffffffffffffffffffffffffffffffff85169163fb93210891604480830192600092919082900301818387803b158015612f4a57600080fd5b505af1158015612f5e573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff871681526020810185905281517f491c0362a655f805cc3d5ab67c471c6b4e517051540c85134456449ce6c1a6799450908190039091019150a1505050565b612fc1336146aa565b158015612fcd57503332145b61303857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b601c54336000908152601b602052604090205461305690439061449f565b10156130c357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f616374696f6e2064656c6179206e6f74206d6574000000000000000000000000604482015290519081900360640190fd5b336000908152601b602052604081204390819055600c54600b54909290801561314a5760006130f2848661449f565b905060005481106131055781925061312c565b600054613112838361451b565b111561312c57600054613129906110b6848461451b565b92505b82156131485761313c828461449f565b600b556131488361486b565b505b600c83905533600061315b82612315565b905080156131ca57600f54613170908261449f565b600f5573ffffffffffffffffffffffffffffffffffffffff82166000908152600460205260409020546131a3908261460f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460205260409020555b600e5473ffffffffffffffffffffffffffffffffffffffff8316600090815260066020526040812091909155879061320182612315565b9050801561327057600f54613216908261449f565b600f5573ffffffffffffffffffffffffffffffffffffffff8216600090815260046020526040902054613249908261460f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460205260409020555b600e5473ffffffffffffffffffffffffffffffffffffffff831660009081526006602090815260408083209390935533825260079052205460ff1661332a5760098054600090815260086020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915583526007909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915581540190555b73ffffffffffffffffffffffffffffffffffffffff891660009081526004602090815260408083205460039092529091205481116133c957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5472616e736d757465723a20216f766572666c6f770000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8a166000908152600460209081526040808320839055600390915281205461340790839061449f565b73ffffffffffffffffffffffffffffffffffffffff808d1660009081526003602052604080822080549083905560015482517f42966c6800000000000000000000000000000000000000000000000000000000815260048101839052925191975094955093909216926342966c6892602480820193929182900301818387803b15801561349357600080fd5b505af11580156134a7573d6000803e3d6000fd5b5050600a546134b9925090508361449f565b600a55336000908152600460205260409020546134d6908261460f565b3360009081526004602090815260408083209390935573ffffffffffffffffffffffffffffffffffffffff8e168252600590522054613515908361460f565b73ffffffffffffffffffffffffffffffffffffffff8c166000908152600560205260409020819055613546816146b0565b73ffffffffffffffffffffffffffffffffffffffff808d1660009081526005602052604080822082905560025481517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018690529151931692632e1a7d4d9260248084019391929182900301818387803b1580156135c857600080fd5b505af11580156135dc573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff8f16925083156108fc02915083906000818181858888f19350505050158015613623573d6000803e3d6000fd5b506040805133815273ffffffffffffffffffffffffffffffffffffffff8e16602082015280820183905290517fb1e35379b2ed6821c33158f59080978024478baafa855571cd84e46b9848b3ce9181900360600190a1505050505050505050505050565b613690336146aa565b15801561369c57503332145b61370757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b61370f613d4d565b61371881611964565b3360009081526003602052604090205461225081611b8d565b60145473ffffffffffffffffffffffffffffffffffffffff1633146137b757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b601a5460ff161561382957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e736d757465723a20616c726561647920696e697469616c697a656400604482015290519081900360640190fd5b60175473ffffffffffffffffffffffffffffffffffffffff16613897576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260348152602001806159c86034913960400191505060405180910390fd5b6138a081614a24565b50601a80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60145473ffffffffffffffffffffffffffffffffffffffff16331461395457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b6122e581614a24565b60165474010000000000000000000000000000000000000000900460ff1680156139bf575060145473ffffffffffffffffffffffffffffffffffffffff163314806139bf575060165473ffffffffffffffffffffffffffffffffffffffff1633145b613a14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061588b6035913960400191505060405180910390fd5b6122e581614cd9565b601c5481565b33600090815260116020526040812054819060ff16613aa357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e736d757465723a20216b656570657200000000000000000000000000604482015290519081900360640190fd5b6000613ab0601985614683565b6017549091506000908190613adc90849073ffffffffffffffffffffffffffffffffffffffff16614d3f565b604080518381526020810183905281519395509193507f11d2034f4471d11a13f0f1798ceaf0c9db2812d450a0681958ce7d4f2fb97f0992918290030190a1909350915050915091565b60186020526000908152604090205460ff1681565b613b44336146aa565b158015613b5057503332145b613bbb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b613bc3613d4d565b336000908152600360205260409020546122e581611b8d565b60145473ffffffffffffffffffffffffffffffffffffffff163314613c6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613cce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615908602a913960400191505060405180910390fd5b6017805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517f05f3326e0527f309d4015dee3bc3f36e650b53fc823bab69c99847814acfafdf9181900360200190a150565b600b5481565b613d56336146aa565b158015613d6257503332145b613dcd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b601c54336000908152601b6020526040902054613deb90439061449f565b1015613e5857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f616374696f6e2064656c6179206e6f74206d6574000000000000000000000000604482015290519081900360640190fd5b336000908152601b602052604081204390819055600c54600b549092908015613edf576000613e87848661449f565b90506000548110613e9a57819250613ec1565b600054613ea7838361451b565b1115613ec157600054613ebe906110b6848461451b565b92505b8215613edd57613ed1828461449f565b600b55613edd8361486b565b505b600c839055336000613ef082612315565b90508015613f5f57600f54613f05908261449f565b600f5573ffffffffffffffffffffffffffffffffffffffff8216600090815260046020526040902054613f38908261460f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460205260409020555b600e5473ffffffffffffffffffffffffffffffffffffffff831660009081526006602090815260408083209390935533808352600490915291812054908161400857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f6e65656420746f20686176652070656e64696e6720696e206275636b65740000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460209081526040808320839055600390915290205482111561409e5773ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604090205461407390839061449f565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040902054925090505b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260409020546140ce908361449f565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600360205260408082209390935560015483517f42966c680000000000000000000000000000000000000000000000000000000081526004810187905293519216926342966c68926024808301939282900301818387803b15801561414f57600080fd5b505af1158015614163573d6000803e3d6000fd5b5050600a54614175925090508361449f565b600a556141818161486b565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600560205260409020546141b1908361460f565b73ffffffffffffffffffffffffffffffffffffffff841660008181526005602090815260409182902093909355805191825291810184905281517fe6b1330a9c444712d3673f05900d736c42072653e56fb82b5951477832b8d576929181900390910190a1505050505050505050565b60155473ffffffffffffffffffffffffffffffffffffffff1681565b60165473ffffffffffffffffffffffffffffffffffffffff1681565b60036020526000908152604090205481565b3360009081526010602052604090205460ff166142e957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f5472616e736d757465723a202177686974656c69737465640000000000000000604482015290519081900360640190fd5b600c54600b544390600090801561435e576000614306848661449f565b9050600054811061431957819250614340565b600054614326838361451b565b11156143405760005461433d906110b6848461451b565b92505b821561435c57614350828461449f565b600b5561435c8361486b565b505b600c83905560165474010000000000000000000000000000000000000000900460ff16156143ed57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f656d657267656e637920706175736520656e61626c6564000000000000000000604482015290519081900360640190fd5b6002546144129073ffffffffffffffffffffffffffffffffffffffff168730886148d4565b600b5461441f908661460f565b600b5561442a614d92565b6040805173ffffffffffffffffffffffffffffffffffffffff881681526020810187905281517f33ad5d6b2a46b5457e0d36286a2686a0390b0821dedbbdf8dcdcda64f4782c68929181900390910190a1505050505050565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561451057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b60008261452a57506000614515565b8282028284828161453757fe5b0414612384576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806159536021913960400191505060405180910390fd5b60008082116145fe57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161460757fe5b049392505050565b60008282018381101561238457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082600001828154811061469457fe5b9060005260206000209060020201905092915050565b3b151590565b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b15801561472157600080fd5b505afa158015614735573d6000803e3d6000fd5b505050506040513d602081101561474b57600080fd5b505190508181101561225057601254818303906147719061476c908361460f565b614ea6565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052614771908490614edc565b6000614810601984614683565b9050600080614820833086614fb4565b91509150847fccbd929f935422b28ee209a0db0556280b0a3d9bc4da58f1d3f0ab4f8a4996478383604051808381526020018281526020019250505060405180910390a25050505050565b6000600a5411801561487d5750600081115b156148c1576148a96148a0600a546110b6600d548561451b90919063ffffffff16565b600e549061460f565b600e55600f546148b9908261460f565b600f556122e5565b600b546148ce908261460f565b600b5550565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052614969908590614edc565b50505050565b5490565b60008184841115614a1c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156149e15781810151838201526020016149c9565b50505050905090810190601f168015614a0e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b73ffffffffffffffffffffffffffffffffffffffff8116614a90576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615a26602f913960400191505060405180910390fd5b600254604080517ffc0c546a000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9283169284169163fc0c546a916004808301926020929190829003018186803b158015614afd57600080fd5b505afa158015614b11573d6000803e3d6000fd5b505050506040513d6020811015614b2757600080fd5b505173ffffffffffffffffffffffffffffffffffffffff1614614b95576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806159326021913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526018602052604090205460ff1615614c2a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4164617074657220616c726561647920696e2075736500000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600081815260186020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558051808201909152928352820152614c9590601990614fea565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f0821015de34e20b0878a40f6f165801417f53b2017016d7321cacee989c8cfa790600090a250565b6000614ce6601983614683565b9050600080614cf58330615052565b91509150837fccbd929f935422b28ee209a0db0556280b0a3d9bc4da58f1d3f0ab4f8a4996478383604051808381526020018281526020019250505060405180910390a250505050565b6000808360010154614d5085615079565b11614d605750600090508061124d565b6000614d798560010154614d7387615079565b9061449f565b9050614d86858583615115565b92509250509250929050565b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b158015614e0357600080fd5b505afa158015614e17573d6000803e3d6000fd5b505050506040513d6020811015614e2d57600080fd5b5051601354601254919250600091614e4b916064916110b69161451b565b601254909150614e5b908261460f565b821115614e875760125482036000614e73601961532c565b9050614e7f8183615357565b505050612250565b601254614e94908261449f565b82101561225057601254829003614771815b6000614eb2601961532c565b90506000614ebf82615079565b905082811015614ecd578092505b82156147715761477183615434565b6060614f3e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166154479092919063ffffffff16565b80519091501561477157808060200190516020811015614f5d57600080fd5b5051614771576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806159fc602a913960400191505060405180910390fd5b6000808080614fc487878761545e565b60018901549193509150614fd8908261449f565b60018801559092509050935093915050565b8154600180820184556000938452602093849020835160029093020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921782559190920151910155565b60008061506e83856001015486614fb49092919063ffffffff16565b915091509250929050565b8054604080517fd4c3eea0000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163d4c3eea0916004808301926020929190829003018186803b1580156150e357600080fd5b505afa1580156150f7573d6000803e3d6000fd5b505050506040513d602081101561510d57600080fd5b505192915050565b60008060006151238661558c565b905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231876040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561518e57600080fd5b505afa1580156151a2573d6000803e3d6000fd5b505050506040513d60208110156151b857600080fd5b5051905060006151c788615079565b8854604080517f594d4e3600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152602482018b9052915193945091169163594d4e369160448082019260009290919082900301818387803b15801561524357600080fd5b505af1158015615257573d6000803e3d6000fd5b5050505060008373ffffffffffffffffffffffffffffffffffffffff166370a08231896040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156152c457600080fd5b505afa1580156152d8573d6000803e3d6000fd5b505050506040513d60208110156152ee57600080fd5b5051905060006152fe828561449f565b9050600061530b8b615079565b90506000615319858361449f565b929c929b50919950505050505050505050565b600081615338816155f6565b8154811061534257fe5b90600052602060002090600202019050919050565b6000806153638461558c565b845490915061538c9073ffffffffffffffffffffffffffffffffffffffff808416911685614776565b8354604080517fb6b55f2500000000000000000000000000000000000000000000000000000000815260048101869052905173ffffffffffffffffffffffffffffffffffffffff9092169163b6b55f259160248082019260009290919082900301818387803b1580156153fe57600080fd5b505af1158015615412573d6000803e3d6000fd5b505050600185015461542591508461460f565b60018501555081905092915050565b6122e561544160196155f6565b82614803565b6060615456848460008561564f565b949350505050565b600080600061546c8661558c565b905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231876040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156154d757600080fd5b505afa1580156154eb573d6000803e3d6000fd5b505050506040513d602081101561550157600080fd5b50519050600061551088615079565b8854604080517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152602482018b9052915193945091169163f3fef3a39160448082019260009290919082900301818387803b15801561524357600080fd5b8054604080517ffc0c546a000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163fc0c546a916004808301926020929190829003018186803b1580156150e357600080fd5b6000806156028361496f565b905061238460016040518060400160405280601181526020017f5661756c742e4c6973743a20656d707479000000000000000000000000000000815250836149739092919063ffffffff16565b6060824710156156aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806158e26026913960400191505060405180910390fd5b6156b3856146aa565b61571e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061578857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161574b565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146157ea576040519150601f19603f3d011682016040523d82523d6000602084013e6157ef565b606091505b50915091506157ff82828661580a565b979650505050505050565b60608315615819575081612384565b8251156158295782518084602001fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482018181528451602484015284518593919283926044019190850190808383600083156149e15781810151838201526020016149c956fe5472616e736d757465723a206e6f74207061757365642c206f72206e6f7420676f7665726e616e6365206f722073656e74696e656c6e6f7420656e6f7567682066756e647320746f2073657276696365207374616b6573416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5472616e736d757465723a207265776172647320616464726573732063616e6e6f74206265203078302e5472616e736d757465722e7661756c743a20746f6b656e206d69736d617463682e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775472616e736d757465723a20756e7374616b6520616d6f756e742065786365656473206465706f736974656420616d6f756e746d6967726174653a2073657420656d657267656e637920657869742066697273745472616e736d757465723a2063616e6e6f7420696e697469616c697a652072657761726473206164647265737320746f203078305361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645472616e736d757465723a20616374697665207661756c7420616464726573732063616e6e6f74206265203078302e5472616e736d757465723a2073656e74696e656c20616464726573732063616e6e6f74206265203078302ea26469706673582212209540c84023afb357aedc5df5c2a3ef27030e09fb7a43ae07bf12c7e76e6b6bba64736f6c634300060c00330000000000000000000000000100546f2cd4c9d97f798ffc9755e47865ff7ee6000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000e78588283aa9ccbec277b40fb8edfa8cc2155a7

Deployed Bytecode

0x6080604052600436106103c75760003560e01c80638391e45c116101f2578063c2a88e1d1161010d578063ec38a862116100a0578063f58c251c1161006f578063f58c251c14610f47578063f93f394c14610f5c578063fb93210814610f9c578063fc0c546a14610fe2576103ce565b8063ec38a86214610ec8578063edaafe2014610f08578063f1f7920014610f1d578063f39c38a014610f32576103ce565b8063d42c11e1116100dc578063d42c11e114610e1b578063ddc6326214610e30578063e5711ffc14610e73578063e9fad8ee14610eb3576103ce565b8063c2a88e1d14610d45578063c4d66de814610d71578063ce5494bb14610db1578063d2c2949214610df1576103ce565b8063a694fc3a11610185578063b870d59811610154578063b870d59814610c59578063bedb86fb14610c99578063bf51929f14610cc5578063bff170b914610d05576103ce565b8063a694fc3a14610bb0578063a704e8ad14610bda578063a7c6a10014610c1a578063aaf1666014610c2f576103ce565b80639f4216e8116101c15780639f4216e814610b32578063a02fbe2d14610b5c578063a196cf2e14610b86578063a59d698614610b9b576103ce565b80638391e45c14610a9e5780638456cb5914610ade57806394ff119914610af35780639ec5a89414610b1d576103ce565b8063372c12b1116102e2578063658b98a91161027557806378e1270e1161024457806378e1270e146109dd57806379070a1214610a09578063806985f714610a4957806381ac45fb14610a89576103ce565b8063658b98a9146108b45780636790fab3146108c95780636a4f4b05146108de57806370460eb1146109ad576103ce565b806352710007116102b15780635271000714610802578063538ba4f91461084257806353d6fd59146108575780635aa6e6751461089f576103ce565b8063372c12b1146107585780633bbd64bc146107985780633cb802b9146107d85780634bf04bd1146107ed576103ce565b80631acce0301161035a5780632670fdd8116103295780632670fdd81461069a5780632a3d7c81146106ed5780632d81a78e146107025780632e17de781461072e576103ce565b80631acce030146106345780631aeb19861461065b5780632113342d14610670578063238efcbc14610685576103ce565b80630abb6035116103965780630abb60351461053b5780631486bf6e1461057b578063158ef93e146105a55780631959a002146105ce576103ce565b806303036290146103d357806305d2301d1461049c5780630668911e146104cf57806309dac061146104fb576103ce565b366103ce57005b600080fd5b3480156103df57600080fd5b50610403600480360360408110156103f657600080fd5b5080359060200135610ff7565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561044757818101518382015260200161042f565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561048657818101518382015260200161046e565b5050505090500194505050505060405180910390f35b3480156104a857600080fd5b506104b1611254565b60408051938452602084019290925282820152519081900360600190f35b3480156104db57600080fd5b506104f9600480360360208110156104f257600080fd5b503561128e565b005b34801561050757600080fd5b506104f96004803603602081101561051e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661134f565b34801561054757600080fd5b506104f96004803603602081101561055e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166114ba565b34801561058757600080fd5b506104f96004803603602081101561059e57600080fd5b503561163b565b3480156105b157600080fd5b506105ba6116fc565b604080519115158252519081900360200190f35b3480156105da57600080fd5b5061060e600480360360208110156105f157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611705565b604080519485526020850193909352838301919091526060830152519081900360800190f35b34801561064057600080fd5b5061064961181e565b60408051918252519081900360200190f35b34801561066757600080fd5b50610649611824565b34801561067c57600080fd5b5061064961182a565b34801561069157600080fd5b506104f9611830565b3480156106a657600080fd5b506106c4600480360360208110156106bd57600080fd5b5035611932565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156106f957600080fd5b5061064961195e565b34801561070e57600080fd5b506104f96004803603602081101561072557600080fd5b50351515611964565b34801561073a57600080fd5b506104f96004803603602081101561075157600080fd5b5035611b8d565b34801561076457600080fd5b506105ba6004803603602081101561077b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611dfd565b3480156107a457600080fd5b506105ba600480360360208110156107bb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611e12565b3480156107e457600080fd5b50610649611e27565b3480156107f957600080fd5b50610649611e2d565b34801561080e57600080fd5b506106496004803603602081101561082557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611e33565b34801561084e57600080fd5b506106c4611e45565b34801561086357600080fd5b506104f96004803603604081101561087a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001351515611e4a565b3480156108ab57600080fd5b506106c4611f5f565b3480156108c057600080fd5b50610649611f7b565b3480156108d557600080fd5b506106c4611f81565b3480156108ea57600080fd5b506104f96004803603604081101561090157600080fd5b81019060208101813564010000000081111561091c57600080fd5b82018360208201111561092e57600080fd5b8035906020019184602083028401116401000000008311171561095057600080fd5b91939092909160208101903564010000000081111561096e57600080fd5b82018360208201111561098057600080fd5b803590602001918460208302840111640100000000831117156109a257600080fd5b509092509050611f9d565b3480156109b957600080fd5b506104f9600480360360408110156109d057600080fd5b508035906020013561218f565b3480156109e957600080fd5b506104f960048036036020811015610a0057600080fd5b50351515612254565b348015610a1557600080fd5b506105ba60048036036020811015610a2c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166122e8565b348015610a5557600080fd5b5061064960048036036020811015610a6c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166122fd565b348015610a9557600080fd5b5061064961230f565b348015610aaa57600080fd5b5061064960048036036020811015610ac157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612315565b348015610aea57600080fd5b506105ba61238b565b348015610aff57600080fd5b506104f960048036036020811015610b1657600080fd5b50356123ac565b348015610b2957600080fd5b506106c461246d565b348015610b3e57600080fd5b506106c460048036036020811015610b5557600080fd5b5035612489565b348015610b6857600080fd5b506104f960048036036020811015610b7f57600080fd5b50356124b1565b348015610b9257600080fd5b50610649612572565b348015610ba757600080fd5b506104f9612578565b348015610bbc57600080fd5b506104f960048036036020811015610bd357600080fd5b5035612644565b348015610be657600080fd5b5061064960048036036020811015610bfd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612a70565b348015610c2657600080fd5b50610649612a82565b348015610c3b57600080fd5b5061064960048036036020811015610c5257600080fd5b5035612a93565b348015610c6557600080fd5b5061064960048036036020811015610c7c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612aac565b348015610ca557600080fd5b506104f960048036036020811015610cbc57600080fd5b50351515612abe565b348015610cd157600080fd5b506104f960048036036020811015610ce857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612be5565b348015610d1157600080fd5b506104f960048036036020811015610d2857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612fb8565b348015610d5157600080fd5b506104f960048036036020811015610d6857600080fd5b50351515613687565b348015610d7d57600080fd5b506104f960048036036020811015610d9457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613731565b348015610dbd57600080fd5b506104f960048036036020811015610dd457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166138ce565b348015610dfd57600080fd5b506104f960048036036020811015610e1457600080fd5b503561395d565b348015610e2757600080fd5b50610649613a1d565b348015610e3c57600080fd5b50610e5a60048036036020811015610e5357600080fd5b5035613a23565b6040805192835260208301919091528051918290030190f35b348015610e7f57600080fd5b506105ba60048036036020811015610e9657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613b26565b348015610ebf57600080fd5b506104f9613b3b565b348015610ed457600080fd5b506104f960048036036020811015610eeb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613bdc565b348015610f1457600080fd5b50610649613d47565b348015610f2957600080fd5b506104f9613d4d565b348015610f3e57600080fd5b506106c4614221565b348015610f5357600080fd5b506106c461423d565b348015610f6857600080fd5b5061064960048036036020811015610f7f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614259565b348015610fa857600080fd5b506104f960048036036040811015610fbf57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561426b565b348015610fee57600080fd5b506106c4614483565b60608083808403828167ffffffffffffffff8111801561101657600080fd5b50604051908082528060200260200182016040528015611040578160200160208202803683370190505b50905060608260020267ffffffffffffffff8111801561105f57600080fd5b50604051908082528060200260200182016040528015611089578160200160208202803683370190505b5090506000806110bc6000546110b66110ad600c544361449f90919063ffffffff16565b600b549061451b565b9061458e565b90506000546110d6600c544361449f90919063ffffffff16565b11156110e15750600b545b60005b8581101561124157600087815260086020526040902054855173ffffffffffffffffffffffffffffffffffffffff9091169086908390811061112257fe5b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152600089815260088252604080822054909316815260039091522054845185908590811061117257fe5b602090810291909101810191909152600a5460008981526008835260408082205473ffffffffffffffffffffffffffffffffffffffff16825260039093529190912054611214916111c8916110b690869061451b565b60008981526008602081815260408084205473ffffffffffffffffffffffffffffffffffffffff168085526004835290842054938d905291905261120e91908290612315565b9061460f565b84846001018151811061122357fe5b602090810291909101015260019687019660029390930192016110e4565b50929650909450505050505b9250929050565b600080600061126e600c544361449f90919063ffffffff16565b600b546000549193509150611287906110b6838561451b565b9250909192565b60145473ffffffffffffffffffffffffffffffffffffffff16331461131457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b60128190556040805182815290517fe77487d7758cc0f4820329f0d13f96448757377d4bf03ca31ce49cc9e151486f9181900360200190a150565b60145473ffffffffffffffffffffffffffffffffffffffff1633146113d557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116611441576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615a55602b913960400191505060405180910390fd5b6016805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517fdc117600f93282860144d2cd2745f8e2e15c3ca2a32b4290c30f7cd1ae7ffcb99181900360200190a150565b60145473ffffffffffffffffffffffffffffffffffffffff16331461154057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166115c257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f5472616e736d757465723a203020676f76000000000000000000000000000000604482015290519081900360640190fd5b6015805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517fc9e2377236eab4280090ce8f2317332649736d92f00dcf20a8dd6684ec5e78399181900360200190a150565b60145473ffffffffffffffffffffffffffffffffffffffff1633146116c157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b601c8190556040805182815290517f3bff5293be89c925015798c1dfc042b8a1108bad4eb02ba603aea7ed96ac0cfd9181900360200190a150565b601a5460ff1681565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260408120548154600c54839283928392839161174b916110b6906110ad90439061449f565b9050600054611765600c544361449f90919063ffffffff16565b11156117705750600b545b600a5473ffffffffffffffffffffffffffffffffffffffff881660009081526003602052604081205490916117aa916110b690859061451b565b905060006117e66117ba8a612315565b73ffffffffffffffffffffffffffffffffffffffff8b166000908152600460205260409020549061460f565b73ffffffffffffffffffffffffffffffffffffffff999099166000908152600560205260409020549399919897509295509350505050565b60135481565b60125481565b600e5481565b60155473ffffffffffffffffffffffffffffffffffffffff1633146118b657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f2170656e64696e67476f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b601554601480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040805182815290517f9d3e522e1e47a2f6009739342b9cc7b252a1888154e843ab55ee1c81745795ab9181900360200190a150565b600080611940601984614683565b5473ffffffffffffffffffffffffffffffffffffffff169392505050565b600c5481565b61196d336146aa565b15801561197957503332145b6119e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b336000818152600560205260409020546119fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604081208054919055611a30816146b0565b8215611b0a57600254604080517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815260048101849052905173ffffffffffffffffffffffffffffffffffffffff90921691632e1a7d4d9160248082019260009290919082900301818387803b158015611aa957600080fd5b505af1158015611abd573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff8516925083156108fc02915083906000818181858888f19350505050158015611b04573d6000803e3d6000fd5b50611b2e565b600254611b2e9073ffffffffffffffffffffffffffffffffffffffff168383614776565b6002546040805173ffffffffffffffffffffffffffffffffffffffff80861682529092166020830152818101839052517f4831bdd9dcf3048a28319ce81d3cab7a15366bcf449bc7803a539107440809cc9181900360600190a1505050565b611b96336146aa565b158015611ba257503332145b611c0d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b336000611c1982612315565b90508015611c8857600f54611c2e908261449f565b600f5573ffffffffffffffffffffffffffffffffffffffff8216600090815260046020526040902054611c61908261460f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460205260409020555b600e5473ffffffffffffffffffffffffffffffffffffffff831660009081526006602090815260408083209390935533808352600390915291902054841115611d1c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806159746033913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054611d4c908561449f565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260036020526040902055600a54611d7f908561449f565b600a55600154611da69073ffffffffffffffffffffffffffffffffffffffff168286614776565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905281517f51c9b122c2b81c914282042bf02d3a8965f5a0b1ad37b6dab1cb77bb343ce556929181900390910190a150505050565b60106020526000908152604090205460ff1681565b60116020526000908152604090205460ff1681565b600f5481565b600a5481565b60056020526000908152604090205481565b600081565b60145473ffffffffffffffffffffffffffffffffffffffff163314611ed057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526010602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915582519384529083015280517f0aa5ec5ffdc7f6f9c4d0dded489d7450297155cb2f71cb771e02427f7dff4f519281900390910190a15050565b60145473ffffffffffffffffffffffffffffffffffffffff1681565b600d5481565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60145473ffffffffffffffffffffffffffffffffffffffff16331461202357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b8260005b818110156120b85783838281811061203b57fe5b9050602002013515156011600088888581811061205457fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101612027565b507fd1721b10ac5fe95d2627d512aa0f92c34ada0347c874adf414cf51af5760ff56858585856040518080602001806020018381038352878782818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018481038352858152602090810191508690860280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039850909650505050505050a15050505050565b60165474010000000000000000000000000000000000000000900460ff1680156121f1575060145473ffffffffffffffffffffffffffffffffffffffff163314806121f1575060165473ffffffffffffffffffffffffffffffffffffffff1633145b612246576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061588b6035913960400191505060405180910390fd5b6122508282614803565b5050565b61225d336146aa565b15801561226957503332145b6122d457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b6122dc613d4d565b6122e581611964565b50565b60076020526000908152604090205460ff1681565b60066020526000908152604090205481565b60005481565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260066020526040812054600e54829161234a919061449f565b600d5473ffffffffffffffffffffffffffffffffffffffff8516600090815260036020526040902054919250612384916110b6908461451b565b9392505050565b60165474010000000000000000000000000000000000000000900460ff1681565b60145473ffffffffffffffffffffffffffffffffffffffff16331461243257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b60138190556040805182815290517fcf837c6f8ba9f94fb0b21939d04aba4ae1cf50cbeca85513c218dfdc6666f1a99181900360200190a150565b60175473ffffffffffffffffffffffffffffffffffffffff1681565b60086020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60145473ffffffffffffffffffffffffffffffffffffffff16331461253757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b60008190556040805182815290517fc2965d898897107f6f1d0e43c043ca07b7a51d487acfac1decec2ec8405364409181900360200190a150565b60095481565b60145473ffffffffffffffffffffffffffffffffffffffff1633146125fe57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b60145460405173ffffffffffffffffffffffffffffffffffffffff909116904780156108fc02916000818181858888f193505050501580156122e5573d6000803e3d6000fd5b61264d336146aa565b15801561265957503332145b6126c457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b601c54336000908152601b60205260409020546126e290439061449f565b101561274f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f616374696f6e2064656c6179206e6f74206d6574000000000000000000000000604482015290519081900360640190fd5b336000908152601b602052604081204390819055600c54600b5490929080156127d657600061277e848661449f565b90506000548110612791578192506127b8565b60005461279e838361451b565b11156127b8576000546127b5906110b6848461451b565b92505b82156127d4576127c8828461449f565b600b556127d48361486b565b505b600c8390553360006127e782612315565b9050801561285657600f546127fc908261449f565b600f5573ffffffffffffffffffffffffffffffffffffffff821660009081526004602052604090205461282f908261460f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460205260409020555b600e5473ffffffffffffffffffffffffffffffffffffffff831660009081526006602090815260408083209390935533825260079052205460ff166129105760098054600090815260086020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915583526007909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915581540190555b60165474010000000000000000000000000000000000000000900460ff161561299a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f656d657267656e637920706175736520656e61626c6564000000000000000000604482015290519081900360640190fd5b60015433906129c19073ffffffffffffffffffffffffffffffffffffffff1682308b6148d4565b600a546129ce908961460f565b600a5573ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054612a01908961460f565b73ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040918290209390935580519182529181018a905281517fd2c11ddc796e75881f492256edb3cb3bf4c7a7761682320c5798a8dbb3662d88929181900390910190a15050505050505050565b601b6020526000908152604090205481565b6000612a8e601961496f565b905090565b600080612aa1601984614683565b600101549392505050565b60046020526000908152604090205481565b60145473ffffffffffffffffffffffffffffffffffffffff16331480612afb575060165473ffffffffffffffffffffffffffffffffffffffff1633145b612b6657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f2128676f76207c7c2073656e74696e656c290000000000000000000000000000604482015290519081900360640190fd5b601680548215157401000000000000000000000000000000000000000081027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9092169190911790915560408051918252517f77860e247ab9186dbe64e5bd0e0b93273cc4273e01818420e788f500078886f59181900360200190a150565b60145473ffffffffffffffffffffffffffffffffffffffff163314612c6b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116612ced57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f63616e6e6f74206d69677261746520746f203078300000000000000000000000604482015290519081900360640190fd5b60165474010000000000000000000000000000000000000000900460ff16612d60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806159a76021913960400191505060405180910390fd5b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b158015612dd157600080fd5b505afa158015612de5573d6000803e3d6000fd5b505050506040513d6020811015612dfb57600080fd5b5051600a5460408051606081019091526022808252929350600092612e2c9291906158c06020830139849190614973565b600254604080517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260248201859052915193945091169163095ea7b3916044808201926020929091908290030181600087803b158015612eaa57600080fd5b505af1158015612ebe573d6000803e3d6000fd5b505050506040513d6020811015612ed457600080fd5b5050604080517ffb93210800000000000000000000000000000000000000000000000000000000815230600482015260248101839052905173ffffffffffffffffffffffffffffffffffffffff85169163fb93210891604480830192600092919082900301818387803b158015612f4a57600080fd5b505af1158015612f5e573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff871681526020810185905281517f491c0362a655f805cc3d5ab67c471c6b4e517051540c85134456449ce6c1a6799450908190039091019150a1505050565b612fc1336146aa565b158015612fcd57503332145b61303857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b601c54336000908152601b602052604090205461305690439061449f565b10156130c357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f616374696f6e2064656c6179206e6f74206d6574000000000000000000000000604482015290519081900360640190fd5b336000908152601b602052604081204390819055600c54600b54909290801561314a5760006130f2848661449f565b905060005481106131055781925061312c565b600054613112838361451b565b111561312c57600054613129906110b6848461451b565b92505b82156131485761313c828461449f565b600b556131488361486b565b505b600c83905533600061315b82612315565b905080156131ca57600f54613170908261449f565b600f5573ffffffffffffffffffffffffffffffffffffffff82166000908152600460205260409020546131a3908261460f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460205260409020555b600e5473ffffffffffffffffffffffffffffffffffffffff8316600090815260066020526040812091909155879061320182612315565b9050801561327057600f54613216908261449f565b600f5573ffffffffffffffffffffffffffffffffffffffff8216600090815260046020526040902054613249908261460f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460205260409020555b600e5473ffffffffffffffffffffffffffffffffffffffff831660009081526006602090815260408083209390935533825260079052205460ff1661332a5760098054600090815260086020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915583526007909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915581540190555b73ffffffffffffffffffffffffffffffffffffffff891660009081526004602090815260408083205460039092529091205481116133c957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5472616e736d757465723a20216f766572666c6f770000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8a166000908152600460209081526040808320839055600390915281205461340790839061449f565b73ffffffffffffffffffffffffffffffffffffffff808d1660009081526003602052604080822080549083905560015482517f42966c6800000000000000000000000000000000000000000000000000000000815260048101839052925191975094955093909216926342966c6892602480820193929182900301818387803b15801561349357600080fd5b505af11580156134a7573d6000803e3d6000fd5b5050600a546134b9925090508361449f565b600a55336000908152600460205260409020546134d6908261460f565b3360009081526004602090815260408083209390935573ffffffffffffffffffffffffffffffffffffffff8e168252600590522054613515908361460f565b73ffffffffffffffffffffffffffffffffffffffff8c166000908152600560205260409020819055613546816146b0565b73ffffffffffffffffffffffffffffffffffffffff808d1660009081526005602052604080822082905560025481517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018690529151931692632e1a7d4d9260248084019391929182900301818387803b1580156135c857600080fd5b505af11580156135dc573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff8f16925083156108fc02915083906000818181858888f19350505050158015613623573d6000803e3d6000fd5b506040805133815273ffffffffffffffffffffffffffffffffffffffff8e16602082015280820183905290517fb1e35379b2ed6821c33158f59080978024478baafa855571cd84e46b9848b3ce9181900360600190a1505050505050505050505050565b613690336146aa565b15801561369c57503332145b61370757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b61370f613d4d565b61371881611964565b3360009081526003602052604090205461225081611b8d565b60145473ffffffffffffffffffffffffffffffffffffffff1633146137b757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b601a5460ff161561382957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e736d757465723a20616c726561647920696e697469616c697a656400604482015290519081900360640190fd5b60175473ffffffffffffffffffffffffffffffffffffffff16613897576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260348152602001806159c86034913960400191505060405180910390fd5b6138a081614a24565b50601a80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60145473ffffffffffffffffffffffffffffffffffffffff16331461395457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b6122e581614a24565b60165474010000000000000000000000000000000000000000900460ff1680156139bf575060145473ffffffffffffffffffffffffffffffffffffffff163314806139bf575060165473ffffffffffffffffffffffffffffffffffffffff1633145b613a14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061588b6035913960400191505060405180910390fd5b6122e581614cd9565b601c5481565b33600090815260116020526040812054819060ff16613aa357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e736d757465723a20216b656570657200000000000000000000000000604482015290519081900360640190fd5b6000613ab0601985614683565b6017549091506000908190613adc90849073ffffffffffffffffffffffffffffffffffffffff16614d3f565b604080518381526020810183905281519395509193507f11d2034f4471d11a13f0f1798ceaf0c9db2812d450a0681958ce7d4f2fb97f0992918290030190a1909350915050915091565b60186020526000908152604090205460ff1681565b613b44336146aa565b158015613b5057503332145b613bbb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b613bc3613d4d565b336000908152600360205260409020546122e581611b8d565b60145473ffffffffffffffffffffffffffffffffffffffff163314613c6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5472616e736d757465723a2021676f7665726e616e6365000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613cce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615908602a913960400191505060405180910390fd5b6017805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517f05f3326e0527f309d4015dee3bc3f36e650b53fc823bab69c99847814acfafdf9181900360200190a150565b600b5481565b613d56336146aa565b158015613d6257503332145b613dcd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e6f20636f6e74726163742063616c6c73000000000000000000000000000000604482015290519081900360640190fd5b601c54336000908152601b6020526040902054613deb90439061449f565b1015613e5857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f616374696f6e2064656c6179206e6f74206d6574000000000000000000000000604482015290519081900360640190fd5b336000908152601b602052604081204390819055600c54600b549092908015613edf576000613e87848661449f565b90506000548110613e9a57819250613ec1565b600054613ea7838361451b565b1115613ec157600054613ebe906110b6848461451b565b92505b8215613edd57613ed1828461449f565b600b55613edd8361486b565b505b600c839055336000613ef082612315565b90508015613f5f57600f54613f05908261449f565b600f5573ffffffffffffffffffffffffffffffffffffffff8216600090815260046020526040902054613f38908261460f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460205260409020555b600e5473ffffffffffffffffffffffffffffffffffffffff831660009081526006602090815260408083209390935533808352600490915291812054908161400857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f6e65656420746f20686176652070656e64696e6720696e206275636b65740000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152600460209081526040808320839055600390915290205482111561409e5773ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604090205461407390839061449f565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040902054925090505b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260409020546140ce908361449f565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600360205260408082209390935560015483517f42966c680000000000000000000000000000000000000000000000000000000081526004810187905293519216926342966c68926024808301939282900301818387803b15801561414f57600080fd5b505af1158015614163573d6000803e3d6000fd5b5050600a54614175925090508361449f565b600a556141818161486b565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600560205260409020546141b1908361460f565b73ffffffffffffffffffffffffffffffffffffffff841660008181526005602090815260409182902093909355805191825291810184905281517fe6b1330a9c444712d3673f05900d736c42072653e56fb82b5951477832b8d576929181900390910190a1505050505050505050565b60155473ffffffffffffffffffffffffffffffffffffffff1681565b60165473ffffffffffffffffffffffffffffffffffffffff1681565b60036020526000908152604090205481565b3360009081526010602052604090205460ff166142e957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f5472616e736d757465723a202177686974656c69737465640000000000000000604482015290519081900360640190fd5b600c54600b544390600090801561435e576000614306848661449f565b9050600054811061431957819250614340565b600054614326838361451b565b11156143405760005461433d906110b6848461451b565b92505b821561435c57614350828461449f565b600b5561435c8361486b565b505b600c83905560165474010000000000000000000000000000000000000000900460ff16156143ed57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f656d657267656e637920706175736520656e61626c6564000000000000000000604482015290519081900360640190fd5b6002546144129073ffffffffffffffffffffffffffffffffffffffff168730886148d4565b600b5461441f908661460f565b600b5561442a614d92565b6040805173ffffffffffffffffffffffffffffffffffffffff881681526020810187905281517f33ad5d6b2a46b5457e0d36286a2686a0390b0821dedbbdf8dcdcda64f4782c68929181900390910190a1505050505050565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561451057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b60008261452a57506000614515565b8282028284828161453757fe5b0414612384576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806159536021913960400191505060405180910390fd5b60008082116145fe57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161460757fe5b049392505050565b60008282018381101561238457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082600001828154811061469457fe5b9060005260206000209060020201905092915050565b3b151590565b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b15801561472157600080fd5b505afa158015614735573d6000803e3d6000fd5b505050506040513d602081101561474b57600080fd5b505190508181101561225057601254818303906147719061476c908361460f565b614ea6565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052614771908490614edc565b6000614810601984614683565b9050600080614820833086614fb4565b91509150847fccbd929f935422b28ee209a0db0556280b0a3d9bc4da58f1d3f0ab4f8a4996478383604051808381526020018281526020019250505060405180910390a25050505050565b6000600a5411801561487d5750600081115b156148c1576148a96148a0600a546110b6600d548561451b90919063ffffffff16565b600e549061460f565b600e55600f546148b9908261460f565b600f556122e5565b600b546148ce908261460f565b600b5550565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052614969908590614edc565b50505050565b5490565b60008184841115614a1c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156149e15781810151838201526020016149c9565b50505050905090810190601f168015614a0e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b73ffffffffffffffffffffffffffffffffffffffff8116614a90576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615a26602f913960400191505060405180910390fd5b600254604080517ffc0c546a000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9283169284169163fc0c546a916004808301926020929190829003018186803b158015614afd57600080fd5b505afa158015614b11573d6000803e3d6000fd5b505050506040513d6020811015614b2757600080fd5b505173ffffffffffffffffffffffffffffffffffffffff1614614b95576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806159326021913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526018602052604090205460ff1615614c2a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4164617074657220616c726561647920696e2075736500000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600081815260186020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558051808201909152928352820152614c9590601990614fea565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f0821015de34e20b0878a40f6f165801417f53b2017016d7321cacee989c8cfa790600090a250565b6000614ce6601983614683565b9050600080614cf58330615052565b91509150837fccbd929f935422b28ee209a0db0556280b0a3d9bc4da58f1d3f0ab4f8a4996478383604051808381526020018281526020019250505060405180910390a250505050565b6000808360010154614d5085615079565b11614d605750600090508061124d565b6000614d798560010154614d7387615079565b9061449f565b9050614d86858583615115565b92509250509250929050565b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b158015614e0357600080fd5b505afa158015614e17573d6000803e3d6000fd5b505050506040513d6020811015614e2d57600080fd5b5051601354601254919250600091614e4b916064916110b69161451b565b601254909150614e5b908261460f565b821115614e875760125482036000614e73601961532c565b9050614e7f8183615357565b505050612250565b601254614e94908261449f565b82101561225057601254829003614771815b6000614eb2601961532c565b90506000614ebf82615079565b905082811015614ecd578092505b82156147715761477183615434565b6060614f3e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166154479092919063ffffffff16565b80519091501561477157808060200190516020811015614f5d57600080fd5b5051614771576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806159fc602a913960400191505060405180910390fd5b6000808080614fc487878761545e565b60018901549193509150614fd8908261449f565b60018801559092509050935093915050565b8154600180820184556000938452602093849020835160029093020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921782559190920151910155565b60008061506e83856001015486614fb49092919063ffffffff16565b915091509250929050565b8054604080517fd4c3eea0000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163d4c3eea0916004808301926020929190829003018186803b1580156150e357600080fd5b505afa1580156150f7573d6000803e3d6000fd5b505050506040513d602081101561510d57600080fd5b505192915050565b60008060006151238661558c565b905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231876040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561518e57600080fd5b505afa1580156151a2573d6000803e3d6000fd5b505050506040513d60208110156151b857600080fd5b5051905060006151c788615079565b8854604080517f594d4e3600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152602482018b9052915193945091169163594d4e369160448082019260009290919082900301818387803b15801561524357600080fd5b505af1158015615257573d6000803e3d6000fd5b5050505060008373ffffffffffffffffffffffffffffffffffffffff166370a08231896040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156152c457600080fd5b505afa1580156152d8573d6000803e3d6000fd5b505050506040513d60208110156152ee57600080fd5b5051905060006152fe828561449f565b9050600061530b8b615079565b90506000615319858361449f565b929c929b50919950505050505050505050565b600081615338816155f6565b8154811061534257fe5b90600052602060002090600202019050919050565b6000806153638461558c565b845490915061538c9073ffffffffffffffffffffffffffffffffffffffff808416911685614776565b8354604080517fb6b55f2500000000000000000000000000000000000000000000000000000000815260048101869052905173ffffffffffffffffffffffffffffffffffffffff9092169163b6b55f259160248082019260009290919082900301818387803b1580156153fe57600080fd5b505af1158015615412573d6000803e3d6000fd5b505050600185015461542591508461460f565b60018501555081905092915050565b6122e561544160196155f6565b82614803565b6060615456848460008561564f565b949350505050565b600080600061546c8661558c565b905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231876040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156154d757600080fd5b505afa1580156154eb573d6000803e3d6000fd5b505050506040513d602081101561550157600080fd5b50519050600061551088615079565b8854604080517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152602482018b9052915193945091169163f3fef3a39160448082019260009290919082900301818387803b15801561524357600080fd5b8054604080517ffc0c546a000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163fc0c546a916004808301926020929190829003018186803b1580156150e357600080fd5b6000806156028361496f565b905061238460016040518060400160405280601181526020017f5661756c742e4c6973743a20656d707479000000000000000000000000000000815250836149739092919063ffffffff16565b6060824710156156aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806158e26026913960400191505060405180910390fd5b6156b3856146aa565b61571e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061578857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161574b565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146157ea576040519150601f19603f3d011682016040523d82523d6000602084013e6157ef565b606091505b50915091506157ff82828661580a565b979650505050505050565b60608315615819575081612384565b8251156158295782518084602001fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482018181528451602484015284518593919283926044019190850190808383600083156149e15781810151838201526020016149c956fe5472616e736d757465723a206e6f74207061757365642c206f72206e6f7420676f7665726e616e6365206f722073656e74696e656c6e6f7420656e6f7567682066756e647320746f2073657276696365207374616b6573416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5472616e736d757465723a207265776172647320616464726573732063616e6e6f74206265203078302e5472616e736d757465722e7661756c743a20746f6b656e206d69736d617463682e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775472616e736d757465723a20756e7374616b6520616d6f756e742065786365656473206465706f736974656420616d6f756e746d6967726174653a2073657420656d657267656e637920657869742066697273745472616e736d757465723a2063616e6e6f7420696e697469616c697a652072657761726473206164647265737320746f203078305361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645472616e736d757465723a20616374697665207661756c7420616464726573732063616e6e6f74206265203078302e5472616e736d757465723a2073656e74696e656c20616464726573732063616e6e6f74206265203078302ea26469706673582212209540c84023afb357aedc5df5c2a3ef27030e09fb7a43ae07bf12c7e76e6b6bba64736f6c634300060c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000100546f2cd4c9d97f798ffc9755e47865ff7ee6000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000e78588283aa9ccbec277b40fb8edfa8cc2155a7

-----Decoded View---------------
Arg [0] : _alToken (address): 0x0100546F2cD4C9D97f798fFC9755E47865FF7Ee6
Arg [1] : _token (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [2] : _governance (address): 0x0e78588283aA9CcBeC277b40fB8eDfa8Cc2155a7

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000100546f2cd4c9d97f798ffc9755e47865ff7ee6
Arg [1] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [2] : 0000000000000000000000000e78588283aa9ccbec277b40fb8edfa8cc2155a7


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.