Goerli Testnet

Contract

0x4827b97709B2E8cf1F53Da11f7Fb069CD18F739d
Source Code

Overview

ETH Balance

0 ETH

Multi Chain

Multichain Addresses

N/A
Transaction Hash
Method
Block
From
To
Value
0x6080604083048672023-01-13 15:13:36330 days 16 hrs ago1673622816IN
 Create: Parser
0 ETH0.01456893.76642715

Latest 25 internal transactions (View All)

Advanced mode:
Parent Txn Hash Block From To Value
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
92126412023-06-20 23:35:24172 days 7 hrs ago1687304124
0x4827b9...D18F739d
0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Parser

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
No with 100 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 12 : Parser.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import { IERC20 } from './interfaces/IERC20.sol';
import { IDSLContext } from './interfaces/IDSLContext.sol';
import { IProgramContext } from './interfaces/IProgramContext.sol';
import { IParser } from './interfaces/IParser.sol';
import { IPreprocessor } from './interfaces/IPreprocessor.sol';
import { StringUtils } from './libs/StringUtils.sol';
import { ByteUtils } from './libs/ByteUtils.sol';
import { Preprocessor } from './Preprocessor.sol';
import { ErrorsParser } from './libs/Errors.sol';

// import 'hardhat/console.sol';

/**
 * @dev Parser of DSL code. This contract is a singleton and should not
 * be deployed more than once
 *
 * One of the core contracts of the project. It parses DSL expression
 * that comes from user. After parsing code in Parser
 * a bytecode of the DSL program is generated as stored in ProgramContext
 *
 * DSL code in postfix notation as string -> Parser -> raw bytecode
 */
contract Parser is IParser {
    using StringUtils for string;
    using ByteUtils for bytes;

    string[] internal cmds; // DSL code in postfix form (output of Preprocessor)
    uint256 internal cmdIdx; // Current parsing index of DSL code

    /**
     * @dev Transform DSL code from array in infix notation to raw bytecode
     * @param _dslCtxAddr DSLContext contract address
     * @param _programCtxAddr ProgramContext contract address
     * @param _codeRaw Input code as a string in infix notation
     */
    function parse(
        address _preprAddr,
        address _dslCtxAddr,
        address _programCtxAddr,
        string memory _codeRaw
    ) external {
        string[] memory _code = IPreprocessor(_preprAddr).transform(_dslCtxAddr, _codeRaw);
        parseCode(_dslCtxAddr, _programCtxAddr, _code);
    }

    /**
     * @dev Сonverts a list of commands to bytecode
     */
    function parseCode(address _dslCtxAddr, address _programCtxAddr, string[] memory _code) public {
        cmdIdx = 0;
        bytes memory b;
        bytes memory program;

        IProgramContext(_programCtxAddr).setProgram(b); // TODO: set to 0 that program in the program context
        _setCmdsArray(_code); // remove empty strings
        IProgramContext(_programCtxAddr).setPc(0);
        IProgramContext(_programCtxAddr).stack().clear();

        while (cmdIdx < cmds.length) {
            program = _parseOpcodeWithParams(_dslCtxAddr, _programCtxAddr, program);
        }
        IProgramContext(_programCtxAddr).setProgram(program);
    }

    /**
     * @dev Asm functions
     * Concatenates the previous program bytecode with the next command
     * that contains in the `cmds` list. `cmdIdx` is helping to follow
     * what exactly the command is in the process
     * Example of code for :
     * ```
     * cmds = ['bool', 'true'] // current cmds
     * cmdIdx = 0 // current parsing index of DSL code
     * program = ''
     * ```
     *
     * So it will be executed the asmSetLocalBool() function where:
     * - `_parseVariable()` internal function will update the previous empty
     * `program` with the bytecode of `bool` opcode
     *
     * Result is `program = '0x18'` (see Context.sol for `addOpcode('bool'..)`
     * to check the code for `bool` opcode)
     * cmdIdx = 0 // current parsing index of DSL code is the same
     *
     * - `asmBool()` function will concatenate previous `program` with the bytecode of `true` value
     * `program` with the bytecode `0x01` (see return values for Parser.sol for `asmBool()` function
     *
     * ```
     * cmdIdx = 1 // parsing index of DSL code was updated
     * program = '0x1801'
     * ```
     */

    /**
     * @dev Updates the program with the bool value
     *
     * Example of a command:
     * ```
     * bool true
     * ```
     */
    function asmSetLocalBool(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program);
        newProgram = asmBool(newProgram, address(0), address(0));
    }

    /**
     * @dev Updates the program with the local variable value
     *
     * Example of a command:
     * ```
     * (uint256 5 + uint256 7) setUint256 VARNAME
     * ```
     */
    function asmSetUint256(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        return _parseVariable(_program);
    }

    /**
     * @dev Updates the program with the name(its position) of the array
     *
     * Example of a command:
     * ```
     * declare ARR_NAME
     * ```
     */
    function asmDeclare(
        bytes memory _program,
        address _ctxDSLAddr,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseBranchOf(_program, _ctxDSLAddr, 'declareArr'); // program += bytecode for type of array
        newProgram = _parseVariable(newProgram); // program += bytecode for `ARR_NAME`
    }

    function asmCompound(
        bytes memory _program,
        address _ctxDSLAddr,
        address
    ) public returns (bytes memory newProgram) {
        // program += bytecode for type of transaction for compound contract (deposit/withdraw)
        newProgram = _parseBranchOf(_program, _ctxDSLAddr, 'compound');
        _nextCmd(); // skip `all` keyword
        newProgram = _parseVariable(newProgram); // program += bytecode for `TOKEN`
    }

    /**
     * @dev Updates the program with the element by index from the provived array's name
     *
     * Example of a command:
     * ```
     * get 3 USERS
     * ```
     */
    function asmGet(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        string memory _value = _nextCmd();
        bytes4 _arrName = bytes4(keccak256(abi.encodePacked(_nextCmd())));
        newProgram = bytes.concat(_program, bytes32(_value.toUint256()), _arrName);
    }

    /**
     * @dev Updates the program with the new item for the array, can be `uint256`,
     * `address` and `struct name` types.
     *
     * Example of a command:
     * ```
     * push ITEM ARR_NAME
     * ```
     */
    function asmPush(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        string memory _value = _nextCmd();
        bytes4 _arrName = bytes4(keccak256(abi.encodePacked(_nextCmd())));

        if (_value.mayBeAddress()) {
            bytes memory _sliced = bytes(_value).slice(2, 42); // without first `0x` symbols
            newProgram = bytes.concat(_program, bytes32(_sliced.fromHexBytes()));
        } else if (_value.mayBeNumber()) {
            newProgram = bytes.concat(_program, bytes32(_value.toUint256()));
        } else {
            // only for struct names!
            newProgram = bytes.concat(
                _program,
                bytes32(bytes4(keccak256(abi.encodePacked(_value))))
            );
        }

        newProgram = bytes.concat(newProgram, _arrName);
    }

    /**
     * @dev Updates the program with the loadLocal variable
     *
     * Example of command:
     * ```
     * var NUMBER
     * ```
     */
    function asmVar(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program);
    }

    /**
     * @dev Updates the program with the loadRemote variable
     *
     * Example of a command:
     * ```
     * loadRemote bool MARY_ADDRESS 9A676e781A523b5d0C0e43731313A708CB607508
     * ```
     */
    function asmLoadRemote(
        bytes memory _program,
        address _ctxDSLAddr,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseBranchOf(_program, _ctxDSLAddr, 'loadRemote'); // program += bytecode for `loadRemote bool`
        newProgram = _parseVariable(newProgram); // program += bytecode for `MARY_ADDRESS`
        newProgram = _parseAddress(newProgram); // program += bytecode for `9A676e781A523b5...`
    }

    /**
     * @dev Concatenates and updates previous `program` with the `0x01`
     * bytecode of `true` value otherwise `0x00` for `false`
     */
    function asmBool(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        bytes1 value = bytes1(_nextCmd().equal('true') ? 0x01 : 0x00);
        newProgram = bytes.concat(_program, value);
    }

    /**
     * @dev Concatenates and updates previous `program` with the
     * bytecode of uint256 value
     */
    function asmUint256(bytes memory _program, address, address) public returns (bytes memory) {
        uint256 value = _nextCmd().toUint256();
        return bytes.concat(_program, bytes32(value));
    }

    /**
     * @dev Updates previous `program` with the amount that will be send (in wei)
     *
     * Example of a command:
     * ```
     * sendEth RECEIVER 1234
     * ```
     */
    function asmSend(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program); // program += bytecode for `sendEth RECEIVER`
        newProgram = asmUint256(newProgram, address(0), address(0)); // program += bytecode for `1234`
    }

    /**
     * @dev Updates previous `program` with the amount of tokens
     * that will be transfer to reciever(in wei). The `TOKEN` and `RECEIVER`
     * parameters should be stored in smart contract
     *
     * Example of a command:
     * ```
     * transfer TOKEN RECEIVER 1234
     * ```
     */
    function asmTransfer(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program); // token address
        newProgram = _parseVariable(newProgram); // receiver address
        newProgram = asmUint256(newProgram, address(0), address(0)); // amount
    }

    /**
     * @dev Updates previous `program` with the amount of tokens
     * that will be transfer to reciever(in wei). The `TOKEN`, `RECEIVER`, `AMOUNT`
     * parameters should be stored in smart contract
     *
     * Example of a command:
     * ```
     * transferVar TOKEN RECEIVER AMOUNT
     * ```
     */
    function asmTransferVar(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program); // token address
        newProgram = _parseVariable(newProgram); // receiver
        newProgram = _parseVariable(newProgram); // amount
    }

    /**
     * @dev Updates previous `program` with the amount of tokens
     * that will be transfer from the certain address to reciever(in wei).
     * The `TOKEN`, `FROM`, `TO` address parameters should be stored in smart contract
     *
     * Example of a command:
     * ```
     * transferFrom TOKEN FROM TO 1234
     * ```
     */
    function asmTransferFrom(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program); // token address
        newProgram = _parseVariable(newProgram); // from
        newProgram = _parseVariable(newProgram); // to
        newProgram = asmUint256(newProgram, address(0), address(0)); // amount
    }

    /**
     * @dev Updates previous `program` with the amount of tokens
     * that will be transfer from the certain address to reciever(in wei).
     * The `TOKEN`, `FROM`, `TO`, `AMOUNT` parameters should be stored in smart contract
     *
     * Example of a command:
     * ```
     * transferFromVar TOKEN FROM TO AMOUNT
     * ```
     */
    function asmTransferFromVar(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program); // token address
        newProgram = _parseVariable(newProgram); // from
        newProgram = _parseVariable(newProgram); // to
        newProgram = _parseVariable(newProgram); // amount
    }

    /**
     * @dev Updates previous `program` with getting the amount of tokens
     * The `TOKEN`, `USER` address parameters should be stored in smart contract
     *
     * Example of a command:
     * ```
     * balanceOf TOKEN USER
     * ```
     */
    function asmBalanceOf(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program); // token address
        newProgram = _parseVariable(newProgram); // user address
    }

    function asmAllowanceMintBurn(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program); // token address, token address, token address
        newProgram = _parseVariable(newProgram); // owner, to, owner
        newProgram = _parseVariable(newProgram); // spender, amount, amount
    }

    /**
     * @dev Updates previous `program` with getting the length of the dsl array by its name
     * The command return non zero value only if the array name was declared and have at least one value.
     * Check: `declareArr` and `push` commands for DSL arrays
     *
     * Example of a command:
     * ```
     * lengthOf ARR_NAME
     * ```
     */
    function asmLengthOf(bytes memory _program, address, address) public returns (bytes memory) {
        return _parseVariable(_program); // array name
    }

    /**
     * @dev Updates previous `program` with the name of the dsl array that will
     * be used to sum uint256 variables
     *
     * Example of a command:
     * ```
     * sumOf ARR_NAME
     * ```
     */
    function asmSumOf(bytes memory _program, address, address) public returns (bytes memory) {
        return _parseVariable(_program); // array name
    }

    /**
     * @dev Updates previous `program` with the name of the dsl array and
     * name of variable in the DSL structure that will
     * be used to sum uint256 variables
     *
     * Example of a command:
     * ```
     * struct BOB {
     *   lastPayment: 3
     * }
     *
     * struct ALISA {
     *   lastPayment: 300
     * }
     *
     * sumThroughStructs USERS.lastPayment
     * or shorter version
     * sumOf USERS.lastPayment
     * ```
     */
    function asmSumThroughStructs(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program); // array name
        newProgram = _parseVariable(newProgram); // variable name
    }

    /**
     * @dev Updates previous `program` for positive and negative branch position
     *
     * Example of a command:
     * ```
     * 6 > 5 // condition is here must return true or false
     * ifelse AA BB
     * end
     *
     * branch AA {
     *   // code for `positive` branch
     * }
     *
     * branch BB {
     *   // code for `negative` branch
     * }
     * ```
     */
    function asmIfelse(
        bytes memory _program,
        address,
        address _programCtxAddr
    ) public returns (bytes memory newProgram) {
        string memory _true = _nextCmd(); // "positive" branch name
        string memory _false = _nextCmd(); // "negative" branch name
        // set `positive` branch position
        _setLabelPos(_programCtxAddr, _true, _program.length);
        newProgram = bytes.concat(_program, bytes2(0)); // placeholder for `positive` branch offset
        // set `negative` branch position
        _setLabelPos(_programCtxAddr, _false, newProgram.length);
        newProgram = bytes.concat(newProgram, bytes2(0)); // placeholder for `negative` branch offset
    }

    /**
     * @dev Updates previous `program` for positive branch position
     *
     * Example of a command:
     * ```
     * 6 > 5 // condition is here must return true or false
     * if POSITIVE_ACTION
     * end
     *
     * POSITIVE_ACTION {
     *   // code for `positive` branch
     * }
     * ```
     */
    function asmIf(
        bytes memory _program,
        address,
        address _programCtxAddr
    ) public returns (bytes memory newProgram) {
        _setLabelPos(_programCtxAddr, _nextCmd(), _program.length);
        newProgram = bytes.concat(_program, bytes2(0)); // placeholder for `true` branch offset
    }

    /**
     * @dev Updates previous `program` for function code
     *
     * Example of a command:
     * ```
     * func NAME_OF_FUNCTION
     *
     * NAME_OF_FUNCTION {
     *   // code for the body of function
     * }
     * ```
     */
    function asmFunc(
        bytes memory _program,
        address,
        address _programCtxAddr
    ) public returns (bytes memory newProgram) {
        // set `name of function` position
        _setLabelPos(_programCtxAddr, _nextCmd(), _program.length);
        newProgram = bytes.concat(_program, bytes2(0)); // placeholder for `name of function` offset
    }

    /**
     * @dev Updates previous `program` for DSL struct.
     * This function rebuilds variable parameters using a name of the structure, dot symbol
     * and the name of each parameter in the structure
     *
     * Example of DSL command:
     * ```
     * struct BOB {
     *   account: 0x47f8a90ede3d84c7c0166bd84a4635e4675accfc,
     *   lastPayment: 3
     * }
     * ```
     *
     * Example of commands that uses for this functions:
     * `cmds = ['struct', 'BOB', 'lastPayment', '3', 'account', '0x47f..', 'endStruct']`
     *
     * `endStruct` word is used as an indicator for the ending loop for the structs parameters
     */
    function asmStruct(
        bytes memory _program,
        address,
        address _programCtxAddr
    ) public returns (bytes memory newProgram) {
        // parse the name of structure - `BOB`
        string memory _structName = _nextCmd();
        newProgram = _program;
        // parsing name/value parameters till found the 'endStruct' word
        do {
            // parse the name of variable - `balance`, `account`
            string memory _variable = _nextCmd();
            // create the struct name of variable - `BOB.balance`, `BOB.account`
            string memory _name = _structName.concat('.').concat(_variable);
            // TODO: let's think how not to use setter in Parser here..
            IProgramContext(_programCtxAddr).setStructVars(_structName, _variable, _name);
            // TODO: store sertain bytes for each word separate in bytes string?
            newProgram = bytes.concat(newProgram, bytes4(keccak256(abi.encodePacked(_name))));
            // parse the value of `balance` variable - `456`, `0x345...`
            string memory _value = _nextCmd();
            if (_value.mayBeAddress()) {
                // remove first `0x` symbols
                bytes memory _sliced = bytes(_value).slice(2, 42);
                newProgram = bytes.concat(newProgram, bytes32(_sliced.fromHexBytes()));
            } else if (_value.mayBeNumber()) {
                newProgram = bytes.concat(newProgram, bytes32(_value.toUint256()));
            } else if (_variable.equal('vote') && _value.equal('YES')) {
                // voting process, change stored value in the array 1
                newProgram = bytes.concat(newProgram, bytes32(uint256(1)));
            } else if (_variable.equal('vote') && _value.equal('NO')) {
                // voting process, change stored value in the array to 0
                newProgram = bytes.concat(newProgram, bytes32(0));
            }
            // else {
            //     // if the name of the variable
            //     program = bytes.concat(program, bytes32(keccak256(abi.encodePacked(_value))));
            // }
        } while (!(cmds[cmdIdx].equal('endStruct')));

        newProgram = _parseVariable(newProgram); // parse the 'endStruct' word
    }

    /**
     * @dev Parses variable names in for-loop & skip the unnecessary `in` parameter
     * Ex. ['for', 'LP_INITIAL', 'in', 'LPS_INITIAL']
     */
    function asmForLoop(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        // parse temporary variable name
        newProgram = _parseVariable(_program);
        _nextCmd(); // skip `in` keyword
        newProgram = _parseVariable(newProgram);
    }

    /**
     * @dev Parses the `record id` and the `agreement address` parameters
     * Ex. ['enableRecord', 'RECORD_ID', 'at', 'AGREEMENT_ADDRESS']
     */
    function asmEnableRecord(
        bytes memory _program,
        address,
        address
    ) public returns (bytes memory newProgram) {
        newProgram = _parseVariable(_program);
        _nextCmd(); // skip `at` keyword
        newProgram = _parseVariable(newProgram);
    }

    /**
     * Internal functions
     */

    /**
     * @dev returns `true` if the name of `if/ifelse branch` or `function` exists in the labelPos list
     * otherwise returns `false`
     */
    function _isLabel(address _programCtxAddr, string memory _name) internal view returns (bool) {
        return _getLabelPos(_programCtxAddr, _name) > 0;
    }

    function _getLabelPos(
        address _programCtxAddr,
        string memory _name
    ) internal view returns (uint256) {
        return IProgramContext(_programCtxAddr).labelPos(_name);
    }

    /**
     * @dev Updates the bytecode `program` in dependence on
     * commands that were provided in `cmds` list
     */
    function _parseOpcodeWithParams(
        address _dslCtxAddr,
        address _programCtxAddr,
        bytes memory _program
    ) internal returns (bytes memory newProgram) {
        string storage cmd = _nextCmd();

        bytes1 opcode = IDSLContext(_dslCtxAddr).opCodeByName(cmd);

        // TODO: simplify
        bytes4 _selector = bytes4(keccak256(abi.encodePacked(cmd)));
        bool isStructVar = IProgramContext(_programCtxAddr).isStructVar(cmd);
        if (_isLabel(_programCtxAddr, cmd)) {
            bytes2 _branchLocation = bytes2(uint16(_program.length));
            uint256 labelPos = _getLabelPos(_programCtxAddr, cmd);
            newProgram = bytes.concat(
                _program.slice(0, labelPos), // programBefore
                _branchLocation,
                _program.slice(labelPos + 2, _program.length) // programAfter
            );

            // TODO: move isValidVarName() check to Preprocessor
            //       (it should automatically add `var` before all variable names)
        } else if (cmd.isValidVarName() || isStructVar) {
            opcode = IDSLContext(_dslCtxAddr).opCodeByName('var');
            newProgram = bytes.concat(_program, opcode, _selector);
        } else if (opcode == 0x0) {
            revert(string(abi.encodePacked('Parser: "', cmd, '" command is unknown')));
        } else {
            newProgram = bytes.concat(_program, opcode);

            _selector = IDSLContext(_dslCtxAddr).asmSelectors(cmd);
            if (_selector != 0x0) {
                // TODO: address, address
                (bool success, bytes memory data) = address(this).delegatecall(
                    abi.encodeWithSelector(_selector, newProgram, _dslCtxAddr, _programCtxAddr)
                );
                require(success, ErrorsParser.PRS1);
                newProgram = abi.decode(data, (bytes));
            }
            // if no selector then opcode without params
        }
    }

    /**
     * @dev Returns next commad from the cmds list, increases the
     * command index `cmdIdx` by 1
     * @return nextCmd string
     */
    function _nextCmd() internal returns (string storage) {
        return cmds[cmdIdx++];
    }

    /**
     * @dev Updates previous `program` with the next provided command
     */
    function _parseVariable(bytes memory _program) internal returns (bytes memory newProgram) {
        bytes4 _cmd = bytes4(keccak256(abi.encodePacked(_nextCmd())));
        newProgram = bytes.concat(_program, _cmd);
    }

    /**
     * @dev Updates previous `program` with the branch name, like `loadLocal` or `loadRemote`
     * of command and its additional used type
     */
    function _parseBranchOf(
        bytes memory _program,
        address _ctxDSLAddr,
        string memory baseOpName
    ) internal returns (bytes memory newProgram) {
        newProgram = bytes.concat(
            _program,
            IDSLContext(_ctxDSLAddr).branchCodes(baseOpName, _nextCmd())
        );
    }

    /**
     * @dev Updates previous `program` with the address command that is a value
     */
    function _parseAddress(bytes memory _program) internal returns (bytes memory newProgram) {
        string memory _addr = _nextCmd();
        _addr = _addr.substr(2, _addr.length()); // cut `0x` from the beginning of the address
        newProgram = bytes.concat(_program, _addr.fromHex());
    }

    /**
     * @dev Deletes empty elements from the _input array and sets the result as a `cmds` storage array
     */
    function _setCmdsArray(string[] memory _input) internal {
        uint256 i;
        delete cmds;

        while (i < _input.length && !_input[i].equal('')) {
            cmds.push(_input[i++]);
        }
    }

    function _setLabelPos(address _programCtxAddr, string memory _name, uint256 _value) internal {
        IProgramContext(_programCtxAddr).setLabelPos(_name, _value);
    }
}

File 2 of 12 : IDSLContext.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import '../helpers/Stack.sol';

interface IDSLContext {
    enum OpcodeLibNames {
        ComparisonOpcodes,
        BranchingOpcodes,
        LogicalOpcodes,
        OtherOpcodes
    }

    function comparisonOpcodes() external view returns (address);

    function branchingOpcodes() external view returns (address);

    function logicalOpcodes() external view returns (address);

    function otherOpcodes() external view returns (address);

    function opCodeByName(string memory _name) external view returns (bytes1 _opcode);

    function selectorByOpcode(bytes1 _opcode) external view returns (bytes4 _selecotor);

    function numOfArgsByOpcode(string memory _name) external view returns (uint8 _numOfArgs);

    function isCommand(string memory _name) external view returns (bool _isCommand);

    function opcodeLibNameByOpcode(bytes1 _opcode) external view returns (OpcodeLibNames _name);

    function asmSelectors(string memory _name) external view returns (bytes4 _selecotor);

    function opsPriors(string memory _name) external view returns (uint256 _priority);

    function operators(uint256 _index) external view returns (string memory _operator);

    function branchSelectors(
        string memory _baseOpName,
        bytes1 _branchCode
    ) external view returns (bytes4 _selector);

    function branchCodes(
        string memory _baseOpName,
        string memory _branchName
    ) external view returns (bytes1 _branchCode);

    function aliases(string memory _alias) external view returns (string memory _baseCmd);

    // Functions
    function operatorsLen() external view returns (uint256);
}

File 3 of 12 : IParser.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import { IDSLContext } from './IDSLContext.sol';
import { Preprocessor } from '../Preprocessor.sol';

interface IParser {
    // Variables

    event ExecRes(bool result);
    event NewConditionalTx(address txObj);

    // Functions

    function parse(
        address _preprAddr,
        address _dslCtxAddr,
        address _programCtxAddr,
        string memory _codeRaw
    ) external;

    function parseCode(
        address _dslCtxAddr,
        address _programCtxAddr,
        string[] memory _code
    ) external;

    function asmSetLocalBool(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmSetUint256(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmVar(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmLoadRemote(
        bytes memory _program,
        address _ctxDSLAddr,
        address
    ) external returns (bytes memory newProgram);

    function asmDeclare(
        bytes memory _program,
        address _ctxDSLAddr,
        address
    ) external returns (bytes memory newProgram);

    function asmCompound(
        bytes memory _program,
        address _ctxDSLAddr,
        address
    ) external returns (bytes memory newProgram);

    function asmBool(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmUint256(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmSend(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmTransfer(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmTransferVar(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmTransferFrom(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmBalanceOf(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmAllowanceMintBurn(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmLengthOf(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmSumOf(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmSumThroughStructs(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmTransferFromVar(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmIfelse(
        bytes memory _program,
        address _ctxDSLAddr,
        address _programCtxAddr
    ) external returns (bytes memory newProgram);

    function asmIf(
        bytes memory _program,
        address _ctxDSLAddr,
        address _programCtxAddr
    ) external returns (bytes memory newProgram);

    function asmFunc(
        bytes memory _program,
        address _ctxDSLAddr,
        address _programCtxAddr
    ) external returns (bytes memory newProgram);

    function asmGet(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmPush(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmStruct(
        bytes memory _program,
        address _ctxDSLAddr,
        address _programCtxAddr
    ) external returns (bytes memory newProgram);

    function asmForLoop(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);

    function asmEnableRecord(
        bytes memory _program,
        address,
        address
    ) external returns (bytes memory newProgram);
}

File 4 of 12 : Preprocessor.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import { IDSLContext } from './interfaces/IDSLContext.sol';
import { IPreprocessor } from './interfaces/IPreprocessor.sol';
import { StringStack } from './libs/StringStack.sol';
import { StringUtils } from './libs/StringUtils.sol';
import { ErrorsPreprocessor } from './libs/Errors.sol';

/**
 * @dev Preprocessor of DSL code
 * @dev This contract is a singleton and should not be deployed more than once
 *
 * It can remove comments that were created by user in the DSL code string. It
 * transforms the users DSL code string to the list of commands that can be used
 * in a Parser contract.
 *
 * DSL code in postfix notation as
 * user's string code -> Preprocessor -> each command is separated in the commands list
 */
library Preprocessor {
    using StringUtils for string;
    using StringStack for string[];

    /************************
     * == MAIN FUNCTIONS == *
     ***********************/

    /**
     * @dev The main function that transforms the user's DSL code string to the list of commands.
     *
     * Example:
     * The user's DSL code string is
     * ```
     * uint256 6 setUint256 A
     * ```
     * The end result after executing a `transform()` function is
     * ```
     * ['uint256', '6', 'setUint256', 'A']
     * ```
     *
     * @param _ctxAddr is a context contract address
     * @param _program is a user's DSL code string
     * @return code The list of commands that storing `result`
     */
    function transform(
        address _ctxAddr,
        string memory _program
    ) external view returns (string[] memory code) {
        // _program = removeComments(_program);
        code = split(_program, '\n ,:(){}', '(){}');
        code = removeSyntacticSugar(code);
        code = simplifyCode(code, _ctxAddr);
        code = infixToPostfix(_ctxAddr, code);
        return code;
    }

    /**
     * @dev Searches the comments in the program and removes comment lines
     * Example:
     * The user's DSL code string is
     * ```
     *  bool true
     *  // uint256 2 * uint256 5
     * ```
     * The end result after executing a `removeComments()` function is
     * ```
     * bool true
     * ```
     * @param _program is a current program string
     * @return _cleanedProgram new string program that contains only clean code without comments
     */
    function removeComments(
        string memory _program
    ) public pure returns (string memory _cleanedProgram) {
        bool isCommented;

        // searchedSymbolLen is a flag that uses for searching a correct end symbol
        uint256 searchedSymbolLen; // 1 - search \n symbol, 2 - search */ symbol
        uint256 tempIndex; // uses for checking if the index was changed
        uint256 i;
        string memory char;

        while (i < _program.length()) {
            char = _program.char(i);
            tempIndex = i;
            if (isCommented) {
                (tempIndex, isCommented) = _getEndCommentSymbol(
                    searchedSymbolLen,
                    i,
                    _program,
                    char
                );
            } else {
                (searchedSymbolLen, tempIndex, isCommented) = _getCommentSymbol(i, _program, char);
            }

            if (tempIndex > i) {
                i = tempIndex;
                continue;
            }

            if (isCommented) {
                i += 1;
                continue;
            }

            _cleanedProgram = _cleanedProgram.concat(char);
            i += 1;
        }
    }

    /**
     * @dev Splits the user's DSL code string to the list of commands
     * avoiding several symbols:
     * - removes additional and useless symbols as ' ', `\\n`
     * - defines and adding help 'end' symbol for the ifelse condition
     * - defines and cleans the code from `{` and `}` symbols
     *
     * Example:
     * The user's DSL code string is
     * ```
     * (var TIMESTAMP > var INIT)
     * ```
     * The end result after executing a `split()` function is
     * ```
     * ['var', 'TIMESTAMP', '>', 'var', 'INIT']
     * ```
     *
     * @param _program is a user's DSL code string
     * @param _separators Separators that will be used to split the string
     * @param _separatorsToKeep we're using symbols from this string as separators but not removing
     *                          them from the resulting array
     * @return The list of commands that storing in `result`
     */
    function split(
        string memory _program,
        string memory _separators,
        string memory _separatorsToKeep
    ) public pure returns (string[] memory) {
        string[] memory _result = new string[](50);
        uint256 resultCtr;
        string memory buffer; // here we collect DSL commands, var names, etc. symbol by symbol
        string memory char;

        for (uint256 i = 0; i < _program.length(); i++) {
            char = _program.char(i);

            if (char.isIn(_separators)) {
                if (buffer.length() > 0) {
                    _result[resultCtr++] = buffer;
                    buffer = '';
                }
            } else {
                buffer = buffer.concat(char);
            }

            if (char.isIn(_separatorsToKeep)) {
                _result[resultCtr++] = char;
            }
        }

        if (buffer.length() > 0) {
            _result[resultCtr++] = buffer;
            buffer = '';
        }

        return _result;
    }

    /**
     * @dev Removes scientific notation from numbers and removes currency symbols
     * Example
     * 1e3 = 1,000
     * 1 GWEI = 1,000,000,000
     * 1 ETH = 1,000,000,000,000,000,000
     * @param _code Array of DSL commands
     * @return Code without syntactic sugar
     */
    function removeSyntacticSugar(string[] memory _code) public pure returns (string[] memory) {
        string[] memory _result = new string[](50);
        uint256 _resultCtr;
        string memory _chunk;
        string memory _prevChunk;
        uint256 i;

        while (i < _nonEmptyArrLen(_code)) {
            _prevChunk = i == 0 ? '' : _code[i - 1];
            _chunk = _code[i++];

            _chunk = _checkScientificNotation(_chunk);
            if (_isCurrencySymbol(_chunk)) {
                (_resultCtr, _chunk) = _processCurrencySymbol(_resultCtr, _chunk, _prevChunk);
            }

            _result[_resultCtr++] = _chunk;
        }
        return _result;
    }

    /**
     * @dev Depending on the type of the command it gets simplified
     * @param _code Array of DSL commands
     * @param _ctxAddr Context contract address
     * @return Simplified code
     */
    function simplifyCode(
        string[] memory _code,
        address _ctxAddr
    ) public view returns (string[] memory) {
        string[] memory _result = new string[](50);
        uint256 _resultCtr;
        string memory _chunk;
        string memory _prevChunk;
        uint256 i;

        while (i < _nonEmptyArrLen(_code)) {
            _prevChunk = i == 0 ? '' : _code[i - 1];
            _chunk = _code[i++];

            if (IDSLContext(_ctxAddr).isCommand(_chunk)) {
                (_result, _resultCtr, i) = _processCommand(_result, _resultCtr, _code, i, _ctxAddr);
            } else if (_isCurlyBracket(_chunk)) {
                (_result, _resultCtr) = _processCurlyBracket(_result, _resultCtr, _chunk);
            } else if (_isAlias(_chunk, _ctxAddr)) {
                (_result, _resultCtr) = _processAlias(_result, _resultCtr, _ctxAddr, _chunk);
            } else if (_chunk.equal('insert')) {
                (_result, _resultCtr, i) = _processArrayInsert(_result, _resultCtr, _code, i);
            } else {
                (_result, _resultCtr) = _checkIsNumberOrAddress(_result, _resultCtr, _chunk);
                _result[_resultCtr++] = _chunk;
            }
        }
        return _result;
    }

    /**
     * @dev Transforms code in infix format to the postfix format
     * @param _code Array of DSL commands
     * @param _ctxAddr Context contract address
     * @return Code in the postfix format
     */
    function infixToPostfix(
        address _ctxAddr,
        string[] memory _code
    ) public view returns (string[] memory) {
        string[] memory _result = new string[](50);
        string[] memory _stack = new string[](50);
        uint256 _resultCtr;
        string memory _chunk;
        uint256 i;

        while (i < _nonEmptyArrLen(_code)) {
            _chunk = _code[i++];

            if (_isOperator(_chunk, _ctxAddr)) {
                (_result, _resultCtr, _stack) = _processOperator(
                    _stack,
                    _result,
                    _resultCtr,
                    _ctxAddr,
                    _chunk
                );
            } else if (_isParenthesis(_chunk)) {
                (_result, _resultCtr, _stack) = _processParenthesis(
                    _stack,
                    _result,
                    _resultCtr,
                    _chunk
                );
            } else {
                _result[_resultCtr++] = _chunk;
            }
        }

        // Note: now we have a stack with DSL commands and we will pop from it and save to the resulting array to move
        //       from postfix to infix notation
        while (_stack.stackLength() > 0) {
            (_stack, _result[_resultCtr++]) = _stack.popFromStack();
        }
        return _result;
    }

    /***************************
     * == PROCESS FUNCTIONS == *
     **************************/

    /**
     * @dev Process insert into array command
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _code Current DSL code that we're processing
     * @param i Current pointer to the element in _code array that we're processing
     * @return Modified _result array, mofified _resultCtr, and modified `i`
     */
    function _processArrayInsert(
        string[] memory _result,
        uint256 _resultCtr,
        string[] memory _code,
        uint256 i
    ) internal pure returns (string[] memory, uint256, uint256) {
        // Get the necessary params of `insert` command
        // Notice: `insert 1234 into NUMBERS` -> `push 1234 NUMBERS`
        string memory _insertVal = _code[i];
        string memory _arrName = _code[i + 2];

        _result[_resultCtr++] = 'push';
        _result[_resultCtr++] = _insertVal;
        _result[_resultCtr++] = _arrName;

        return (_result, _resultCtr, i + 3);
    }

    /**
     * @dev Process summing over array comand
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _code Current DSL code that we're processing
     * @param i Current pointer to the element in _code array that we're processing
     * @return Modified _result array, mofified _resultCtr, and modified `i`
     */
    function _processSumOfCmd(
        string[] memory _result,
        uint256 _resultCtr,
        string[] memory _code,
        uint256 i
    ) internal pure returns (string[] memory, uint256, uint256) {
        // Ex. (sumOf) `USERS.balance` -> ['USERS', 'balance']
        // Ex. (sumOf) `USERS` ->['USERS']
        string[] memory _sumOfArgs = split(_code[i], '.', '');

        // Ex. `sumOf USERS.balance` -> sum over array of structs
        // Ex. `sumOf USERS` -> sum over a regular array
        if (_nonEmptyArrLen(_sumOfArgs) == 2) {
            // process `sumOf` over array of structs
            _result[_resultCtr++] = 'sumThroughStructs';
            _result[_resultCtr++] = _sumOfArgs[0];
            _result[_resultCtr++] = _sumOfArgs[1];
        } else {
            // process `sumOf` over a regular array
            _result[_resultCtr++] = 'sumOf';
            _result[_resultCtr++] = _sumOfArgs[0];
        }

        return (_result, _resultCtr, i + 1);
    }

    /**
     * @dev Process for-loop
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _code Current DSL code that we're processing
     * @param i Current pointer to the element in _code array that we're processing
     * @return Modified _result array, mofified _resultCtr, and modified `i`
     */
    function _processForCmd(
        string[] memory _result,
        uint256 _resultCtr,
        string[] memory _code,
        uint256 i
    ) internal pure returns (string[] memory, uint256, uint256) {
        // TODO
    }

    /**
     * @dev Process `struct` comand
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _code Current DSL code that we're processing
     * @param i Current pointer to the element in _code array that we're processing
     * @return Modified _result array, mofified _resultCtr, and modified `i`
     */
    function _processStruct(
        string[] memory _result,
        uint256 _resultCtr,
        string[] memory _code,
        uint256 i
    ) internal pure returns (string[] memory, uint256, uint256) {
        // 'struct', 'BOB', '{', 'balance', '456', '}'
        _result[_resultCtr++] = 'struct';
        _result[_resultCtr++] = _code[i]; // struct name
        // skip `{` (index is i + 1)

        uint256 j = i + 1;
        while (!_code[j + 1].equal('}')) {
            _result[_resultCtr++] = _code[j + 1]; // struct key
            _result[_resultCtr++] = _code[j + 2]; // struct value

            j = j + 2;
        }
        _result[_resultCtr++] = 'endStruct';

        return (_result, _resultCtr, j + 2);
    }

    /**
     * @dev Process `ETH`, `WEI` symbols in the code
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _chunk The current piece of code that we're processing (should be the currency symbol)
     * @param _prevChunk The previous piece of code
     * @return Mofified _resultCtr, and modified `_prevChunk`
     */
    function _processCurrencySymbol(
        uint256 _resultCtr,
        string memory _chunk,
        string memory _prevChunk
    ) internal pure returns (uint256, string memory) {
        uint256 _currencyMultiplier = _getCurrencyMultiplier(_chunk);

        try _prevChunk.toUint256() {
            _prevChunk = StringUtils.toString(_prevChunk.toUint256() * _currencyMultiplier);
        } catch {
            _prevChunk = StringUtils.toString(
                _prevChunk.parseScientificNotation().toUint256() * _currencyMultiplier
            );
        }

        // this is to rewrite old number (ex. 100) with an extended number (ex. 100 GWEI = 100000000000)
        if (_resultCtr > 0) {
            --_resultCtr;
        }

        return (_resultCtr, _prevChunk);
    }

    /**
     * @dev Process DSL alias
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _ctxAddr Context contract address
     * @param _chunk The current piece of code that we're processing
     * @return Modified _result array, mofified _resultCtr, and modified `i`
     */
    function _processAlias(
        string[] memory _result,
        uint256 _resultCtr,
        address _ctxAddr,
        string memory _chunk
    ) internal view returns (string[] memory, uint256) {
        uint256 i;

        // Replace alises with base commands
        _chunk = IDSLContext(_ctxAddr).aliases(_chunk);

        // Process multi-command aliases
        // Ex. `uint256[]` -> `declareArr uint256`
        string[] memory _chunks = split(_chunk, ' ', '');

        // while we've not finished processing all the program - keep going
        while (i < _nonEmptyArrLen(_chunks)) {
            _result[_resultCtr++] = _chunks[i++];
        }

        return (_result, _resultCtr);
    }

    /**
     * @dev Process any DSL command
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _code Current DSL code that we're processing
     * @param i Current pointer to the element in _code array that we're processing
     * @param _ctxAddr Context contract address
     * @return Modified _result array, mofified _resultCtr, and modified `i`
     */
    function _processCommand(
        string[] memory _result,
        uint256 _resultCtr,
        string[] memory _code,
        uint256 i,
        address _ctxAddr
    ) internal view returns (string[] memory, uint256, uint256) {
        string memory _chunk = _code[i - 1];
        if (_chunk.equal('struct')) {
            (_result, _resultCtr, i) = _processStruct(_result, _resultCtr, _code, i);
        } else if (_chunk.equal('sumOf')) {
            (_result, _resultCtr, i) = _processSumOfCmd(_result, _resultCtr, _code, i);
        } else if (_chunk.equal('for')) {
            (_result, _resultCtr, i) = _processForCmd(_result, _resultCtr, _code, i);
        } else {
            uint256 _skipCtr = IDSLContext(_ctxAddr).numOfArgsByOpcode(_chunk) + 1;

            i--; // this is to include the command name in the loop below
            // add command arguments
            while (_skipCtr > 0) {
                _result[_resultCtr++] = _code[i++];
                _skipCtr--;
            }
        }

        return (_result, _resultCtr, i);
    }

    /**
     * @dev Process open and closed parenthesis
     * @param _stack Stack that is used to process parenthesis
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _chunk The current piece of code that we're processing
     * @return Modified _result array, mofified _resultCtr, and modified _stack
     */
    function _processParenthesis(
        string[] memory _stack,
        string[] memory _result,
        uint256 _resultCtr,
        string memory _chunk
    ) internal pure returns (string[] memory, uint256, string[] memory) {
        if (_chunk.equal('(')) {
            // opening bracket
            _stack = _stack.pushToStack(_chunk);
        } else if (_chunk.equal(')')) {
            // closing bracket
            (_result, _resultCtr, _stack) = _processClosingParenthesis(_stack, _result, _resultCtr);
        }

        return (_result, _resultCtr, _stack);
    }

    /**
     * @dev Process closing parenthesis
     * @param _stack Stack that is used to process parenthesis
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @return Modified _result array, mofified _resultCtr, and modified _stack
     */
    function _processClosingParenthesis(
        string[] memory _stack,
        string[] memory _result,
        uint256 _resultCtr
    ) public pure returns (string[] memory, uint256, string[] memory) {
        while (!_stack.seeLastInStack().equal('(')) {
            (_stack, _result[_resultCtr++]) = _stack.popFromStack();
        }
        (_stack, ) = _stack.popFromStack(); // remove '(' that is left
        return (_result, _resultCtr, _stack);
    }

    /**
     * @dev Process curly brackets
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _chunk The current piece of code that we're processing
     * @return Modified _result array, mofified _resultCtr
     */
    function _processCurlyBracket(
        string[] memory _result,
        uint256 _resultCtr,
        string memory _chunk
    ) internal pure returns (string[] memory, uint256) {
        // if `_chunk` equal `{` - do nothing
        if (_chunk.equal('}')) {
            _result[_resultCtr++] = 'end';
        }

        return (_result, _resultCtr);
    }

    /**
     * @dev Process any operator in DSL
     * @param _stack Stack that is used to process parenthesis
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _ctxAddr Context contract address
     * @param _chunk The current piece of code that we're processing
     * @return Modified _result array, mofified _resultCtr, and modified _stack
     */
    function _processOperator(
        string[] memory _stack,
        string[] memory _result,
        uint256 _resultCtr,
        address _ctxAddr,
        string memory _chunk
    ) internal view returns (string[] memory, uint256, string[] memory) {
        while (
            _stack.stackLength() > 0 &&
            IDSLContext(_ctxAddr).opsPriors(_chunk) <=
            IDSLContext(_ctxAddr).opsPriors(_stack.seeLastInStack())
        ) {
            (_stack, _result[_resultCtr++]) = _stack.popFromStack();
        }
        _stack = _stack.pushToStack(_chunk);

        return (_result, _resultCtr, _stack);
    }

    /**************************
     * == HELPER FUNCTIONS == *
     *************************/

    /**
     * @dev Checks if chunk is a currency symbol
     * @param _chunk is a current chunk from the DSL string code
     * @return True or false based on whether chunk is a currency symbol or not
     */
    function _isCurrencySymbol(string memory _chunk) internal pure returns (bool) {
        return _chunk.equal('ETH') || _chunk.equal('GWEI');
    }

    /**
     * @dev Checks if chunk is an operator
     * @param _ctxAddr Context contract address
     * @return True or false based on whether chunk is an operator or not
     */
    function _isOperator(string memory _chunk, address _ctxAddr) internal view returns (bool) {
        for (uint256 i = 0; i < IDSLContext(_ctxAddr).operatorsLen(); i++) {
            if (_chunk.equal(IDSLContext(_ctxAddr).operators(i))) return true;
        }
        return false;
    }

    /**
     * @dev Checks if a string is an alias to a command from DSL
     * @param _ctxAddr Context contract address
     * @return True or false based on whether chunk is an alias or not
     */
    function _isAlias(string memory _chunk, address _ctxAddr) internal view returns (bool) {
        return !IDSLContext(_ctxAddr).aliases(_chunk).equal('');
    }

    /**
     * @dev Checks if chunk is a parenthesis
     * @param _chunk Current piece of code that we're processing
     * @return True or false based on whether chunk is a parenthesis or not
     */
    function _isParenthesis(string memory _chunk) internal pure returns (bool) {
        return _chunk.equal('(') || _chunk.equal(')');
    }

    /**
     * @dev Checks if chunk is a curly bracket
     * @param _chunk Current piece of code that we're processing
     * @return True or false based on whether chunk is a curly bracket or not
     */
    function _isCurlyBracket(string memory _chunk) internal pure returns (bool) {
        return _chunk.equal('{') || _chunk.equal('}');
    }

    /**
     * @dev Parses scientific notation in the chunk if there is any
     * @param _chunk Current piece of code that we're processing
     * @return Chunk without a scientific notation
     */
    function _checkScientificNotation(string memory _chunk) internal pure returns (string memory) {
        if (_chunk.mayBeNumber() && !_chunk.mayBeAddress()) {
            return _parseScientificNotation(_chunk);
        }
        return _chunk;
    }

    /**
     * @dev As the string of values can be simple and complex for DSL this function returns a number in
     * Wei regardless of what type of number parameter was provided by the user.
     * For example:
     * `uint256 1000000` - simple
     * `uint256 1e6 - complex`
     * @param _chunk provided number
     * @return updatedChunk amount in Wei of provided _chunk value
     */
    function _parseScientificNotation(
        string memory _chunk
    ) internal pure returns (string memory updatedChunk) {
        try _chunk.toUint256() {
            updatedChunk = _chunk;
        } catch {
            updatedChunk = _chunk.parseScientificNotation();
        }
    }

    /**
     * @dev Checks if chunk is a number or address and processes it if so
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @param _chunk Current piece of code that we're processing
     * @return Modified _result array, mofified _resultCtr
     */
    function _checkIsNumberOrAddress(
        string[] memory _result,
        uint256 _resultCtr,
        string memory _chunk
    ) internal pure returns (string[] memory, uint256) {
        if (_chunk.mayBeAddress()) return (_result, _resultCtr);
        if (_chunk.mayBeNumber()) {
            (_result, _resultCtr) = _addUint256(_result, _resultCtr);
        }

        return (_result, _resultCtr);
    }

    /**
     * @dev Adds `uint256` to a number
     * @param _result Output array that the function is modifying
     * @param _resultCtr Current pointer to the empty element in the _result param
     * @return Modified _result array, mofified _resultCtr
     */
    function _addUint256(
        string[] memory _result,
        uint256 _resultCtr
    ) internal pure returns (string[] memory, uint256) {
        if (_resultCtr == 0 || (!(_result[_resultCtr - 1].equal('uint256')))) {
            _result[_resultCtr++] = 'uint256';
        }
        return (_result, _resultCtr);
    }

    /**
     * @dev checks the value, and returns the corresponding multiplier.
     * If it is Ether, then it returns 1000000000000000000,
     * If it is GWEI, then it returns 1000000000
     * @param _chunk is a command from DSL command list
     * @return returns the corresponding multiplier.
     */
    function _getCurrencyMultiplier(string memory _chunk) internal pure returns (uint256) {
        if (_chunk.equal('ETH')) {
            return 1000000000000000000;
        } else if (_chunk.equal('GWEI')) {
            return 1000000000;
        } else return 0;
    }

    /**
     * @dev Checks if a symbol is a comment, then increases `i` to the next
     * no-comment symbol avoiding an additional iteration
     * @param i is a current index of a char that might be changed
     * @param _program is a current program string
     * @param _char Current character
     * @return Searched symbol length
     * @return New index
     * @return Is code commented or not
     */
    function _getCommentSymbol(
        uint256 i,
        string memory _program,
        string memory _char
    ) internal pure returns (uint256, uint256, bool) {
        if (_canGetSymbol(i + 1, _program)) {
            string memory nextChar = _program.char(i + 1);
            if (_char.equal('/') && nextChar.equal('/')) {
                return (1, i + 2, true);
            } else if (_char.equal('/') && nextChar.equal('*')) {
                return (2, i + 2, true);
            }
        }
        return (0, i, false);
    }

    /**
     * @dev Checks if a symbol is an end symbol of a comment, then increases _index to the next
     * no-comment symbol avoiding an additional iteration
     * @param _ssl is a searched symbol len that might be 0, 1, 2
     * @param i is a current index of a char that might be changed
     * @param _p is a current program string
     * @param _char Current character
     * @return A new index of a char
     * @return Is code commented or not
     */
    function _getEndCommentSymbol(
        uint256 _ssl,
        uint256 i,
        string memory _p,
        string memory _char
    ) internal pure returns (uint256, bool) {
        if (_ssl == 1 && _char.equal('\n')) {
            return (i + 1, false);
        } else if (_ssl == 2 && _char.equal('*') && _canGetSymbol(i + 1, _p)) {
            string memory nextChar = _p.char(i + 1);
            if (nextChar.equal('/')) {
                return (i + 2, false);
            }
        }
        return (i, true);
    }

    /**
     * @dev Checks if it is possible to get next char from a _program
     * @param _index is a current index of a char
     * @param _program is a current program string
     * @return True if program has the next symbol, otherwise is false
     */
    function _canGetSymbol(uint256 _index, string memory _program) internal pure returns (bool) {
        try _program.char(_index) {
            return true;
        } catch Error(string memory) {
            return false;
        }
    }

    /**
     * @dev Returns the length of a string array excluding empty elements
     * Ex. nonEmptyArrLen['h', 'e', 'l', 'l', 'o', '', '', '']) == 5 (not 8)
     * @param _arr Input string array
     * @return i The legth of the array excluding empty elements
     */
    function _nonEmptyArrLen(string[] memory _arr) internal pure returns (uint256 i) {
        while (i < _arr.length && !_arr[i].equal('')) {
            i++;
        }
    }
}

File 5 of 12 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 6 of 12 : IProgramContext.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import '../helpers/Stack.sol';

interface IProgramContext {
    // Variables
    function ANYONE() external view returns (address);

    function stack() external view returns (Stack);

    function program() external view returns (bytes memory);

    function currentProgram() external view returns (bytes memory);

    function programAt(uint256 _start, uint256 _size) external view returns (bytes memory);

    function pc() external view returns (uint256);

    function nextpc() external view returns (uint256);

    function appAddr() external view returns (address);

    function msgSender() external view returns (address);

    function msgValue() external view returns (uint256);

    function isStructVar(string memory _varName) external view returns (bool);

    function labelPos(string memory _name) external view returns (uint256);

    function setLabelPos(string memory _name, uint256 _value) external;

    function forLoopIterationsRemaining() external view returns (uint256);

    function setProgram(bytes memory _data) external;

    function setPc(uint256 _pc) external;

    function setNextPc(uint256 _nextpc) external;

    function incPc(uint256 _val) external;

    function setMsgSender(address _msgSender) external;

    function setMsgValue(uint256 _msgValue) external;

    function setStructVars(
        string memory _structName,
        string memory _varName,
        string memory _fullName
    ) external;

    function structParams(
        bytes4 _structName,
        bytes4 _varName
    ) external view returns (bytes4 _fullName);

    function setForLoopIterationsRemaining(uint256 _forLoopIterationsRemaining) external;
}

File 7 of 12 : StringUtils.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import { ErrorsStringUtils } from './Errors.sol';
import { ByteUtils } from './ByteUtils.sol';

/**
 * @dev Library that simplifies working with strings in Solidity
 */
library StringUtils {
    /**
     * @dev Get character in string by index
     * @param _s Input string
     * @param _index Target index in the string
     * @return Character by index
     */
    function char(string memory _s, uint256 _index) public pure returns (string memory) {
        require(_index < length(_s), ErrorsStringUtils.SUT1);
        bytes memory _sBytes = new bytes(1);
        _sBytes[0] = bytes(_s)[_index];
        return string(_sBytes);
    }

    /**
     * @dev Compares two strings
     * @param _s1 One string
     * @param _s2 Another string
     * @return Are string equal
     */
    function equal(string memory _s1, string memory _s2) internal pure returns (bool) {
        return keccak256(abi.encodePacked(_s1)) == keccak256(abi.encodePacked(_s2));
    }

    /**
     * @dev Gets length of the string
     * @param _s Input string
     * @return The lenght of the string
     */
    function length(string memory _s) internal pure returns (uint256) {
        return bytes(_s).length;
    }

    /**
     * @dev Concats two strings
     * @param _s1 One string
     * @param _s2 Another string
     * @return The concatenation of the strings
     */
    function concat(string memory _s1, string memory _s2) internal pure returns (string memory) {
        return string(abi.encodePacked(_s1, _s2));
    }

    /**
     * @dev Creates a substring from a string
     * Ex. substr('0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE', 2, 42) => '9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE'
     * @param _str Input string
     * @param _start Start index (inclusive)
     * @param _end End index (not inclusive)
     * @return Substring
     */
    function substr(
        string memory _str,
        uint256 _start,
        uint256 _end
    ) public pure returns (string memory) {
        bytes memory strBytes = bytes(_str);
        bytes memory result = new bytes(_end - _start);
        for (uint256 i = _start; i < _end; i++) {
            result[i - _start] = strBytes[i];
        }
        return string(result);
    }

    /**
     * @dev Checks is _char is present in the _string
     * Ex. `_`.in('123_456') => true
     * Ex. `8`.in('123456') => false
     * @param _char Searched character
     * @param _string String to search in
     * @return Is the character presented in the string
     */
    function isIn(string memory _char, string memory _string) public pure returns (bool) {
        for (uint256 i = 0; i < length(_string); i++) {
            if (equal(char(_string, i), _char)) return true;
        }
        return false;
    }

    // Convert an hexadecimal string (without "0x" prefix) to raw bytes
    function fromHex(string memory s) public pure returns (bytes memory) {
        return ByteUtils.fromHexBytes(bytes(s));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation
     * @notice Inspired by OraclizeAPI's implementation - MIT licence
     * https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
     * @param _num Input number
     * @return Number represented as a string
     */
    function toString(uint256 _num) internal pure returns (string memory) {
        if (_num == 0) {
            return '0';
        }
        uint256 _temp = _num;
        uint256 _digits;
        while (_temp != 0) {
            _digits++;
            _temp /= 10;
        }
        bytes memory _buffer = new bytes(_digits);
        while (_num != 0) {
            _digits -= 1;
            _buffer[_digits] = bytes1(uint8(48 + uint256(_num % 10)));
            _num /= 10;
        }
        return string(_buffer);
    }

    /**
     * @dev Converts a decimal number (provided as a string) to uint256
     * @param _s Input decimal number (provided as a string)
     * @return value Unsigned integer from input string
     */
    function toUint256(string memory _s) public pure returns (uint256 value) {
        bytes memory b = bytes(_s);
        uint256 tmp;
        for (uint256 i = 0; i < b.length; i++) {
            tmp = uint8(b[i]);
            require(tmp >= 0x30 && tmp <= 0x39, ErrorsStringUtils.SUT3);
            value = value * 10 + (tmp - 0x30); // 0x30 ascii is '0'
        }
    }

    /**
     * @dev Converts a decimal number (provided as a string) with e symbol (1e18) to number (returned as a string)
     * @param _s Input decimal number (provided as a string)
     * @return result Unsigned integer in a string format
     */
    function parseScientificNotation(string memory _s) public pure returns (string memory result) {
        bool isFound; // was `e` symbol found
        uint256 tmp;
        bytes memory b = bytes(_s);
        string memory base;
        string memory decimals;

        for (uint256 i = 0; i < b.length; i++) {
            tmp = uint8(b[i]);

            if (tmp >= 0x30 && tmp <= 0x39) {
                if (!isFound) {
                    base = concat(base, string(abi.encodePacked(b[i])));
                } else {
                    decimals = concat(decimals, string(abi.encodePacked(b[i])));
                }
            } else if (tmp == 0x65 && !isFound) {
                isFound = true;
            } else {
                // use only one `e` sympol between values without spaces; example: 1e18 or 456e10
                revert(ErrorsStringUtils.SUT5);
            }
        }

        require(!equal(base, ''), ErrorsStringUtils.SUT9);
        require(!equal(decimals, ''), ErrorsStringUtils.SUT6);
        result = toString(toUint256(base) * (10 ** toUint256(decimals)));
    }

    /**
     * @dev If the string starts with a number, so we assume that it's a number.
     * @param _string is a current string for checking
     * @return isNumber that is true if the string starts with a number, otherwise is false
     */
    function mayBeNumber(string memory _string) public pure returns (bool) {
        require(!equal(_string, ''), ErrorsStringUtils.SUT7);
        bytes1 _byte = bytes(_string)[0];
        return uint8(_byte) >= 48 && uint8(_byte) <= 57;
    }

    /**
     * @dev If the string starts with `0x` symbols, so we assume that it's an address.
     * @param _string is a current string for checking
     * @return isAddress that is true if the string starts with `0x` symbols, otherwise is false
     */
    function mayBeAddress(string memory _string) public pure returns (bool) {
        require(!equal(_string, ''), ErrorsStringUtils.SUT7);
        if (bytes(_string).length != 42) return false;

        bytes1 _byte = bytes(_string)[0];
        bytes1 _byte2 = bytes(_string)[1];
        return uint8(_byte) == 48 && uint8(_byte2) == 120;
    }

    /**
     * @dev Checks is string is a valid DSL variable name (matches regexp /^([A-Z_$][A-Z\d_$]*)$/g)
     * @param _s is a current string to check
     * @return isCapital whether the string is a valid DSL variable name or not
     */
    function isValidVarName(string memory _s) public pure returns (bool) {
        require(!equal(_s, ''), ErrorsStringUtils.SUT7);

        uint8 A = 0x41;
        uint8 Z = 0x5a;
        uint8 underscore = 0x5f;
        uint8 dollar = 0x24;
        uint8 zero = 0x30;
        uint8 nine = 0x39;

        uint8 symbol;
        // This is the same as applying regexp /^([A-Z_$][A-Z\d_$]*)$/g
        for (uint256 i = 0; i < length(_s); i++) {
            symbol = uint8(bytes(_s)[i]);
            if (
                (i == 0 &&
                    !((symbol >= A && symbol <= Z) || symbol == underscore || symbol == dollar)) ||
                (i > 0 &&
                    !((symbol >= A && symbol <= Z) ||
                        (symbol >= zero && symbol <= nine) ||
                        symbol == underscore ||
                        symbol == dollar))
            ) {
                return false;
            }
        }
        return true;
    }
}

File 8 of 12 : ByteUtils.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import { ErrorsByteUtils } from './Errors.sol';

// import "hardhat/console.sol";

/**
 * Library to simplify working with bytes
 */
library ByteUtils {
    function slice(
        bytes calldata _data,
        uint256 _start,
        uint256 _end
    ) public pure returns (bytes memory) {
        require(_start < _end, ErrorsByteUtils.BUT1);
        require(_end <= _data.length, ErrorsByteUtils.BUT2);
        return _data[_start:_end];
    }

    /**
     * Convert an hexadecimal string in bytes (without "0x" prefix) to raw bytes
     */
    function fromHexBytes(bytes memory ss) public pure returns (bytes memory) {
        require(ss.length % 2 == 0, ErrorsByteUtils.BUT4); // length must be even
        bytes memory r = new bytes(ss.length / 2);
        for (uint256 i = 0; i < ss.length / 2; ++i) {
            r[i] = bytes1(fromHexChar(ss[2 * i]) * 16 + fromHexChar(ss[2 * i + 1]));
        }
        return r;
    }

    /**
     * @dev Convert an hexadecimal character to their value
     */
    function fromHexChar(bytes1 c) public pure returns (uint8) {
        if (c >= bytes1('0') && c <= bytes1('9')) {
            return uint8(c) - uint8(bytes1('0'));
        }
        if (c >= bytes1('a') && c <= bytes1('f')) {
            return 10 + uint8(c) - uint8(bytes1('a'));
        }
        if (c >= bytes1('A') && c <= bytes1('F')) {
            return 10 + uint8(c) - uint8(bytes1('A'));
        }
        revert(ErrorsByteUtils.BUT3);
    }
}

File 9 of 12 : IPreprocessor.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

interface IPreprocessor {
    function transform(
        address _ctxAddr,
        string memory _program
    ) external view returns (string[] memory);
}

File 10 of 12 : Errors.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

// import 'hardhat/console.sol';

/**
 * @title List of Agreement errors
 */
library ErrorsAgreement {
    string constant AGR1 = 'AGR1'; // Agreement: bad record signatory
    string constant AGR2 = 'AGR2'; // Agreement: not all required records are executed
    string constant AGR3 = 'AGR3'; // Agreement: record fulfilment error
    string constant AGR4 = 'AGR4'; // Agreement: signatures are invalid
    string constant AGR5 = 'AGR5'; // Agreement: the transaction should have at least one condition
    string constant AGR6 = 'AGR6'; // Agreement: not all record conditions are satisfied
    string constant AGR7 = 'AGR7'; // Agreement: record already was executed by this signatory
    string constant AGR8 = 'AGR8'; // Agreement: the variable name is reserved
    string constant AGR9 = 'AGR9'; // Agreement: this record does not exist
    string constant AGR10 = 'AGR10'; // Agreement: this record has not yet been archived
    string constant AGR11 = 'AGR11'; // Agreement: not an owner
    string constant AGR12 = 'AGR12'; // Agreement: zero address
    string constant AGR13 = 'AGR13'; // Agreement: the record is not activated
    string constant AGR14 = 'AGR14'; // Agreement: the record is pre-define. can not be changed
    string constant AGR15 = 'AGR15'; // Agreement: time can not be in the past
    string constant AGR16 = 'AGR16'; // Agreement: out of range
}

library ErrorsGovernance {
    string constant GOV1 = 'GOV1'; // Governance: You can not vote YES anymore
    string constant GOV2 = 'GOV2'; // Governance: You can not vote NO anymore
}

/**
 * @title List of Context errors
 */
library ErrorsContext {
    string constant CTX1 = 'CTX1'; // Context: address is zero
    string constant CTX2 = 'CTX2'; // Context: empty opcode selector
    string constant CTX3 = 'CTX3'; // Context: duplicate opcode name or code
    string constant CTX4 = 'CTX4'; // Context: slicing out of range
    string constant CTX5 = 'CTX5'; // Context: duplicate opcode branch
    string constant CTX6 = 'CTX6'; // Context: wrong application address
    string constant CTX7 = 'CTX7'; // Context: the application address has already set
}

/**
 * @title List of Stack errors
 */
library ErrorsStack {
    string constant STK1 = 'STK1'; // Stack: uint256 type mismatch
    string constant STK2 = 'STK2'; // Stack: string type mismatch
    string constant STK3 = 'STK3'; // Stack: address type mismatch
    string constant STK4 = 'STK4'; // Stack: stack is empty
}

/**
 * @title List of OtherOpcodes errors
 */
library ErrorsGeneralOpcodes {
    string constant OP1 = 'OP1'; // Opcodes: opSetLocal call not success
    string constant OP2 = 'OP2'; // Opcodes: tries to get an item from non-existing array
    string constant OP3 = 'OP3'; // Opcodes: opLoadRemote call not success
    string constant OP4 = 'OP4'; // Opcodes: tries to put an item to non-existing array
    string constant OP5 = 'OP5'; // Opcodes: opLoadLocal call not success
    string constant OP6 = 'OP6'; // Opcodes: array is empty
    string constant OP8 = 'OP8'; // Opcodes: wrong type of array
}

/**
 * @title List of BranchingOpcodes errors
 */
library ErrorsBranchingOpcodes {
    string constant BR1 = 'BR1'; // BranchingOpcodes: LinkedList.getType() delegate call error
    string constant BR2 = 'BR2'; // BranchingOpcodes: array doesn't exist
    string constant BR3 = 'BR3'; // BranchingOpcodes: LinkedList.get() delegate call error
}

/**
 * @title List of Parser errors
 */
library ErrorsParser {
    string constant PRS1 = 'PRS1'; // Parser: delegatecall to asmSelector failure
    string constant PRS2 = 'PRS2'; // Parser: the name of variable can not be empty
}

/**
 * @title List of Preprocessor errors
 */
library ErrorsPreprocessor {
    string constant PRP1 = 'PRP1'; // Preprocessor: amount of parameters can not be 0
    string constant PRP2 = 'PRP2'; // Preprocessor: invalid parameters for the function
}

/**
 * @title List of OpcodesHelpers errors
 */
library ErrorsOpcodeHelpers {
    string constant OPH1 = 'OPH1'; // Opcodes: mustCall call not success
    string constant OPH2 = 'OPH2'; // Opcodes: mustDelegateCall call not success
}

/**
 * @title List of ByteUtils errors
 */
library ErrorsByteUtils {
    string constant BUT1 = 'BUT1'; // ByteUtils: 'end' index must be greater than 'start'
    string constant BUT2 = 'BUT2'; // ByteUtils: 'end' is greater than the length of the array
    string constant BUT3 = 'BUT3'; // ByteUtils: a hex value not from the range 0-9, a-f, A-F
    string constant BUT4 = 'BUT4'; // ByteUtils: hex lenght not even
}

/**
 * @title List of Executor errors
 */
library ErrorsExecutor {
    string constant EXC1 = 'EXC1'; // Executor: empty program
    string constant EXC2 = 'EXC2'; // Executor: did not find selector for opcode
    string constant EXC3 = 'EXC3'; // Executor: call not success
    string constant EXC4 = 'EXC4'; // Executor: call to program context not success
}

/**
 * @title List of StringUtils errors
 */
library ErrorsStringUtils {
    string constant SUT1 = 'SUT1'; // StringUtils: index out of range
    string constant SUT3 = 'SUT3'; // StringUtils: non-decimal character
    string constant SUT4 = 'SUT4'; // StringUtils: base was not provided
    string constant SUT5 = 'SUT5'; // StringUtils: invalid format
    string constant SUT6 = 'SUT6'; // StringUtils: decimals were not provided
    string constant SUT7 = 'SUT7'; // StringUtils: a string was not provided
    string constant SUT9 = 'SUT9'; // StringUtils: base was not provided
}

File 11 of 12 : Stack.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import { ErrorsStack } from '../libs/Errors.sol';

contract Stack {
    uint256[] public stack;

    function length() external view returns (uint256) {
        return _length();
    }

    function seeLast() external view returns (uint256) {
        return _seeLast();
    }

    function push(uint256 data) external {
        stack.push(data);
    }

    function pop() external returns (uint256) {
        uint256 data = _seeLast();
        stack.pop();

        return data;
    }

    function clear() external {
        delete stack;
    }

    function _length() internal view returns (uint256) {
        return stack.length;
    }

    function _seeLast() internal view returns (uint256) {
        require(_length() > 0, ErrorsStack.STK4);
        return stack[_length() - 1];
    }
}

File 12 of 12 : StringStack.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import { ErrorsStack } from '../libs/Errors.sol';
import { StringUtils } from './StringUtils.sol';

// TODO: add tests for this file
/**
 * @dev This library has all the functions to use solidity string array as a struct
 */
library StringStack {
    using StringUtils for string;

    /**
     * @dev Push element to array in the first position
     * As the array has fixed size, we drop the last element
     * when addind a new one to the beginning of the array
     * @param _stack String stack
     * @param _element String to be added to the stack
     * @return Modified stack
     */
    function pushToStack(
        string[] memory _stack,
        string memory _element
    ) external pure returns (string[] memory) {
        _stack[stackLength(_stack)] = _element;
        return _stack;
    }

    function popFromStack(
        string[] memory _stack
    ) external pure returns (string[] memory, string memory) {
        string memory _topElement = seeLastInStack(_stack);
        _stack[stackLength(_stack) - 1] = '';
        return (_stack, _topElement);
    }

    function stackLength(string[] memory _stack) public pure returns (uint256) {
        uint256 i;
        while (!_stack[i].equal('')) {
            i++;
        }
        return i;
    }

    function seeLastInStack(string[] memory _stack) public pure returns (string memory) {
        uint256 _len = stackLength(_stack);
        require(_len > 0, ErrorsStack.STK4);
        return _stack[_len - 1];
    }
}

Settings
{
  "optimizer": {
    "enabled": false,
    "runs": 100
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {
    "contracts/dsl/libs/ByteUtils.sol": {
      "ByteUtils": "0x1c407cdd4975532bb5f3f614fb3b48478f597f49"
    },
    "contracts/dsl/libs/StringUtils.sol": {
      "StringUtils": "0xd816c20e28cc704028c475108f4dc535e237ebd9"
    }
  }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"result","type":"bool"}],"name":"ExecRes","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"txObj","type":"address"}],"name":"NewConditionalTx","type":"event"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmAllowanceMintBurn","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmBalanceOf","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmBool","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"_ctxDSLAddr","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmCompound","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"_ctxDSLAddr","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmDeclare","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmEnableRecord","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmForLoop","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_programCtxAddr","type":"address"}],"name":"asmFunc","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmGet","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_programCtxAddr","type":"address"}],"name":"asmIf","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_programCtxAddr","type":"address"}],"name":"asmIfelse","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmLengthOf","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"_ctxDSLAddr","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmLoadRemote","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmPush","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmSend","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmSetLocalBool","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmSetUint256","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_programCtxAddr","type":"address"}],"name":"asmStruct","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmSumOf","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmSumThroughStructs","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmTransfer","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmTransferFrom","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmTransferFromVar","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmTransferVar","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmUint256","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_program","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"asmVar","outputs":[{"internalType":"bytes","name":"newProgram","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_preprAddr","type":"address"},{"internalType":"address","name":"_dslCtxAddr","type":"address"},{"internalType":"address","name":"_programCtxAddr","type":"address"},{"internalType":"string","name":"_codeRaw","type":"string"}],"name":"parse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_dslCtxAddr","type":"address"},{"internalType":"address","name":"_programCtxAddr","type":"address"},{"internalType":"string[]","name":"_code","type":"string[]"}],"name":"parseCode","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50614523806100206000396000f3fe608060405234801561001057600080fd5b50600436106101845760003560e01c806390d95d80116100d9578063c45e3e5011610087578063c45e3e5014610551578063c92b45e114610581578063cbfc5ad4146105b1578063cedba5f1146105e1578063dc19dabd14610611578063f5a4363e14610641578063f7edbb701461067157610184565b806390d95d80146104155780639609ebb3146104455780639714a18214610461578063997f430614610491578063b9c34291146104c1578063b9dd4c83146104f1578063bfd5b4451461052157610184565b80635887e21b116101365780635887e21b146102d957806368bf5659146103095780636960e80b14610339578063861826411461036957806386b8d4e81461039957806389995a9e146103c95780638bc0a7a7146103e557610184565b8063021d30be1461018957806303dc1cee146101b957806305feb51f146101e95780630f47ec74146102195780632909fb3e1461024957806353edd023146102795780635694922f146102a9575b600080fd5b6101a3600480360381019061019e91906130d0565b6106a1565b6040516101b091906131c7565b60405180910390f35b6101d360048036038101906101ce91906130d0565b6106b5565b6040516101e091906131c7565b60405180910390f35b61020360048036038101906101fe91906130d0565b6106dd565b60405161021091906131c7565b60405180910390f35b610233600480360381019061022e91906130d0565b610851565b60405161024091906131c7565b60405180910390f35b610263600480360381019061025e91906130d0565b610865565b60405161027091906131c7565b60405180910390f35b610293600480360381019061028e91906130d0565b6109a4565b6040516102a091906131c7565b60405180910390f35b6102c360048036038101906102be91906130d0565b6109b8565b6040516102d091906131c7565b60405180910390f35b6102f360048036038101906102ee91906130d0565b6109e5565b60405161030091906131c7565b60405180910390f35b610323600480360381019061031e91906130d0565b610a44565b60405161033091906131c7565b60405180910390f35b610353600480360381019061034e91906130d0565b610a66565b60405161036091906131c7565b60405180910390f35b610383600480360381019061037e91906130d0565b610abc565b60405161039091906131c7565b60405180910390f35b6103b360048036038101906103ae91906130d0565b610b1d565b6040516103c091906131c7565b60405180910390f35b6103e360048036038101906103de9190613370565b610b3c565b005b6103ff60048036038101906103fa91906130d0565b610d89565b60405161040c91906131c7565b60405180910390f35b61042f600480360381019061042a91906130d0565b610ea4565b60405161043c91906131c7565b60405180910390f35b61045f600480360381019061045a91906133df565b610eb8565b005b61047b600480360381019061047691906130d0565b610f4f565b60405161048891906131c7565b60405180910390f35b6104ab60048036038101906104a691906130d0565b6117a5565b6040516104b891906131c7565b60405180910390f35b6104db60048036038101906104d691906130d0565b6117dd565b6040516104e891906131c7565b60405180910390f35b61050b600480360381019061050691906130d0565b6118aa565b60405161051891906131c7565b60405180910390f35b61053b600480360381019061053691906130d0565b611ce8565b60405161054891906131c7565b60405180910390f35b61056b600480360381019061056691906130d0565b611d10565b60405161057891906131c7565b60405180910390f35b61059b600480360381019061059691906130d0565b611d3a565b6040516105a891906131c7565b60405180910390f35b6105cb60048036038101906105c691906130d0565b611d5c565b6040516105d891906131c7565b60405180910390f35b6105fb60048036038101906105f691906130d0565b611ef9565b60405161060891906131c7565b60405180910390f35b61062b600480360381019061062691906130d0565b611fc6565b60405161063891906131c7565b60405180910390f35b61065b600480360381019061065691906130d0565b611ff0565b60405161066891906131c7565b60405180910390f35b61068b600480360381019061068691906130d0565b61200f565b60405161069891906131c7565b60405180910390f35b60606106ac84612044565b90509392505050565b60606106c084612044565b90506106ca6120a2565b506106d481612044565b90509392505050565b606060006106e96120a2565b80546106f490613491565b80601f016020809104026020016040519081016040528092919081815260200182805461072090613491565b801561076d5780601f106107425761010080835404028352916020019161076d565b820191906000526020600020905b81548152906001019060200180831161075057829003601f168201915b50505050509050600061077e6120a2565b60405160200161078e9190613562565b604051602081830303815290604052805190602001209050858273d816c20e28cc704028c475108f4dc535e237ebd96370121b7190916040518263ffffffff1660e01b81526004016107e091906135ce565b602060405180830381865af41580156107fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108219190613626565b60001b8260405160200161083793929190613707565b604051602081830303815290604052925050509392505050565b606061085c84612044565b90509392505050565b606060006108716120a2565b805461087c90613491565b80601f01602080910402602001604051908101604052809291908181526020018280546108a890613491565b80156108f55780601f106108ca576101008083540402835291602001916108f5565b820191906000526020600020905b8154815290600101906020018083116108d857829003601f168201915b505050505073d816c20e28cc704028c475108f4dc535e237ebd96370121b7190916040518263ffffffff1660e01b815260040161093291906135ce565b602060405180830381865af415801561094f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109739190613626565b9050848160001b60405160200161098b929190613740565b6040516020818303038152906040529150509392505050565b60606109af84612044565b90509392505050565b60606109c384612044565b90506109ce81612044565b90506109dc81600080610865565b90509392505050565b6060610a2784846040518060400160405280600881526020017f636f6d706f756e640000000000000000000000000000000000000000000000008152506120dc565b9050610a316120a2565b50610a3b81612044565b90509392505050565b6060610a4f84612044565b9050610a5d81600080610d89565b90509392505050565b6060610aa884846040518060400160405280600a81526020017f6465636c617265417272000000000000000000000000000000000000000000008152506120dc565b9050610ab381612044565b90509392505050565b6060610afe84846040518060400160405280600a81526020017f6c6f616452656d6f7465000000000000000000000000000000000000000000008152506120dc565b9050610b0981612044565b9050610b148161218b565b90509392505050565b6060610b2884612044565b9050610b3381612044565b90509392505050565b60006001819055506060808373ffffffffffffffffffffffffffffffffffffffff1663bcf80c9d836040518263ffffffff1660e01b8152600401610b8091906131c7565b600060405180830381600087803b158015610b9a57600080fd5b505af1158015610bae573d6000803e3d6000fd5b50505050610bbb83612358565b8373ffffffffffffffffffffffffffffffffffffffff1663f26c917860006040518263ffffffff1660e01b8152600401610bf591906137ad565b600060405180830381600087803b158015610c0f57600080fd5b505af1158015610c23573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff1663138ef1516040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c969190613806565b73ffffffffffffffffffffffffffffffffffffffff166352efea6e6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610cdd57600080fd5b505af1158015610cf1573d6000803e3d6000fd5b505050505b6000805490506001541015610d1757610d10858583612421565b9050610cf6565b8373ffffffffffffffffffffffffffffffffffffffff1663bcf80c9d826040518263ffffffff1660e01b8152600401610d5091906131c7565b600060405180830381600087803b158015610d6a57600080fd5b505af1158015610d7e573d6000803e3d6000fd5b505050505050505050565b60606000610e656040518060400160405280600481526020017f7472756500000000000000000000000000000000000000000000000000000000815250610dce6120a2565b8054610dd990613491565b80601f0160208091040260200160405190810160405280929190818152602001828054610e0590613491565b8015610e525780601f10610e2757610100808354040283529160200191610e52565b820191906000526020600020905b815481529060010190602001808311610e3557829003601f168201915b5050505050612c5490919063ffffffff16565b610e70576000610e73565b60015b60f81b90508481604051602001610e8b929190613880565b6040516020818303038152906040529150509392505050565b6060610eaf84612044565b90509392505050565b60008473ffffffffffffffffffffffffffffffffffffffff16630411de8885846040518363ffffffff1660e01b8152600401610ef5929190613901565b600060405180830381865afa158015610f12573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610f3b9190613a56565b9050610f48848483610b3c565b5050505050565b60606000610f5b6120a2565b8054610f6690613491565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9290613491565b8015610fdf5780601f10610fb457610100808354040283529160200191610fdf565b820191906000526020600020905b815481529060010190602001808311610fc257829003601f168201915b505050505090508491505b6000610ff46120a2565b8054610fff90613491565b80601f016020809104026020016040519081016040528092919081815260200182805461102b90613491565b80156110785780601f1061104d57610100808354040283529160200191611078565b820191906000526020600020905b81548152906001019060200180831161105b57829003601f168201915b5050505050905060006110db826110cd6040518060400160405280600181526020017f2e0000000000000000000000000000000000000000000000000000000000000081525086612cad90919063ffffffff16565b612cad90919063ffffffff16565b90508473ffffffffffffffffffffffffffffffffffffffff1663d598989e8484846040518463ffffffff1660e01b815260040161111a93929190613a9f565b600060405180830381600087803b15801561113457600080fd5b505af1158015611148573d6000803e3d6000fd5b50505050838160405160200161115e9190613b1c565b60405160208183030381529060405280519060200120604051602001611185929190613b33565b604051602081830303815290604052935060006111a06120a2565b80546111ab90613491565b80601f01602080910402602001604051908101604052809291908181526020018280546111d790613491565b80156112245780601f106111f957610100808354040283529160200191611224565b820191906000526020600020905b81548152906001019060200180831161120757829003601f168201915b505050505090508073d816c20e28cc704028c475108f4dc535e237ebd9634863d3e190916040518263ffffffff1660e01b815260040161126491906135ce565b602060405180830381865af4158015611281573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a59190613b93565b156113e457600081731c407cdd4975532bb5f3f614fb3b48478f597f4963e004139690916002602a6040518463ffffffff1660e01b81526004016112eb93929190613c80565b600060405180830381865af4158015611308573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906113319190613d2e565b90508581731c407cdd4975532bb5f3f614fb3b48478f597f49632c16769b90916040518263ffffffff1660e01b815260040161136d9190613d77565b600060405180830381865af415801561138a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906113b39190613d2e565b6113bc90613dcb565b6040516020016113cd929190613740565b60405160208183030381529060405295505061169a565b8073d816c20e28cc704028c475108f4dc535e237ebd963dba27b1c90916040518263ffffffff1660e01b815260040161141d91906135ce565b602060405180830381865af415801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190613b93565b1561150857848173d816c20e28cc704028c475108f4dc535e237ebd96370121b7190916040518263ffffffff1660e01b815260040161149d91906135ce565b602060405180830381865af41580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de9190613626565b60001b6040516020016114f2929190613740565b6040516020818303038152906040529450611699565b6115506040518060400160405280600481526020017f766f74650000000000000000000000000000000000000000000000000000000081525084612c5490919063ffffffff16565b80156115a0575061159f6040518060400160405280600381526020017f594553000000000000000000000000000000000000000000000000000000000081525082612c5490919063ffffffff16565b5b156115d25784600160001b6040516020016115bc929190613740565b6040516020818303038152906040529450611698565b61161a6040518060400160405280600481526020017f766f74650000000000000000000000000000000000000000000000000000000081525084612c5490919063ffffffff16565b801561166a57506116696040518060400160405280600281526020017f4e4f00000000000000000000000000000000000000000000000000000000000081525082612c5490919063ffffffff16565b5b1561169757846000801b604051602001611685929190613740565b60405160208183030381529060405294505b5b5b5b50505061178d6040518060400160405280600981526020017f656e6453747275637400000000000000000000000000000000000000000000008152506000600154815481106116ec576116eb613e32565b5b90600052602060002001805461170190613491565b80601f016020809104026020016040519081016040528092919081815260200182805461172d90613491565b801561177a5780601f1061174f5761010080835404028352916020019161177a565b820191906000526020600020905b81548152906001019060200180831161175d57829003601f168201915b5050505050612c5490919063ffffffff16565b15610fea5761179b82612044565b9150509392505050565b60606117b084612044565b90506117bb81612044565b90506117c681612044565b90506117d481600080610865565b90509392505050565b606061187b826117eb6120a2565b80546117f690613491565b80601f016020809104026020016040519081016040528092919081815260200182805461182290613491565b801561186f5780601f106118445761010080835404028352916020019161186f565b820191906000526020600020905b81548152906001019060200180831161185257829003601f168201915b50505050508651612cd9565b83600060f01b604051602001611892929190613eae565b60405160208183030381529060405290509392505050565b606060006118b66120a2565b80546118c190613491565b80601f01602080910402602001604051908101604052809291908181526020018280546118ed90613491565b801561193a5780601f1061190f5761010080835404028352916020019161193a565b820191906000526020600020905b81548152906001019060200180831161191d57829003601f168201915b50505050509050600061194b6120a2565b60405160200161195b9190613562565b6040516020818303038152906040528051906020012090508173d816c20e28cc704028c475108f4dc535e237ebd9634863d3e190916040518263ffffffff1660e01b81526004016119ac91906135ce565b602060405180830381865af41580156119c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ed9190613b93565b15611b2c57600082731c407cdd4975532bb5f3f614fb3b48478f597f4963e004139690916002602a6040518463ffffffff1660e01b8152600401611a3393929190613c80565b600060405180830381865af4158015611a50573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611a799190613d2e565b90508681731c407cdd4975532bb5f3f614fb3b48478f597f49632c16769b90916040518263ffffffff1660e01b8152600401611ab59190613d77565b600060405180830381865af4158015611ad2573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611afb9190613d2e565b611b0490613dcb565b604051602001611b15929190613740565b604051602081830303815290604052935050611cbb565b8173d816c20e28cc704028c475108f4dc535e237ebd963dba27b1c90916040518263ffffffff1660e01b8152600401611b6591906135ce565b602060405180830381865af4158015611b82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba69190613b93565b15611c5057858273d816c20e28cc704028c475108f4dc535e237ebd96370121b7190916040518263ffffffff1660e01b8152600401611be591906135ce565b602060405180830381865af4158015611c02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c269190613626565b60001b604051602001611c3a929190613740565b6040516020818303038152906040529250611cba565b8582604051602001611c629190613b1c565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916604051602001611ca8929190613740565b60405160208183030381529060405292505b5b8281604051602001611cce929190613b33565b604051602081830303815290604052925050509392505050565b6060611cf384612044565b9050611cfd6120a2565b50611d0781612044565b90509392505050565b6060611d1b84612044565b9050611d2681612044565b9050611d3181612044565b90509392505050565b6060611d4584612044565b9050611d5381600080610865565b90509392505050565b60606000611d686120a2565b8054611d7390613491565b80601f0160208091040260200160405190810160405280929190818152602001828054611d9f90613491565b8015611dec5780601f10611dc157610100808354040283529160200191611dec565b820191906000526020600020905b815481529060010190602001808311611dcf57829003601f168201915b505050505090506000611dfd6120a2565b8054611e0890613491565b80601f0160208091040260200160405190810160405280929190818152602001828054611e3490613491565b8015611e815780601f10611e5657610100808354040283529160200191611e81565b820191906000526020600020905b815481529060010190602001808311611e6457829003601f168201915b50505050509050611e9484838851612cd9565b85600060f01b604051602001611eab929190613eae565b6040516020818303038152906040529250611ec884828551612cd9565b82600060f01b604051602001611edf929190613eae565b604051602081830303815290604052925050509392505050565b6060611f9782611f076120a2565b8054611f1290613491565b80601f0160208091040260200160405190810160405280929190818152602001828054611f3e90613491565b8015611f8b5780601f10611f6057610100808354040283529160200191611f8b565b820191906000526020600020905b815481529060010190602001808311611f6e57829003601f168201915b50505050508651612cd9565b83600060f01b604051602001611fae929190613eae565b60405160208183030381529060405290509392505050565b6060611fd184612044565b9050611fdc81612044565b9050611fe781612044565b90509392505050565b6060611ffb84612044565b905061200681612044565b90509392505050565b606061201a84612044565b905061202581612044565b905061203081612044565b905061203b81612044565b90509392505050565b606060006120506120a2565b6040516020016120609190613562565b604051602081830303815290604052805190602001209050828160405160200161208b929190613b33565b604051602081830303815290604052915050919050565b600080600160008154809291906120b890613f05565b91905055815481106120cd576120cc613e32565b5b90600052602060002001905090565b6060838373ffffffffffffffffffffffffffffffffffffffff16635bf3e5d7846121046120a2565b6040518363ffffffff1660e01b8152600401612121929190613fce565b602060405180830381865afa15801561213e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121629190614031565b604051602001612173929190613880565b60405160208183030381529060405290509392505050565b606060006121976120a2565b80546121a290613491565b80601f01602080910402602001604051908101604052809291908181526020018280546121ce90613491565b801561221b5780601f106121f05761010080835404028352916020019161221b565b820191906000526020600020905b8154815290600101906020018083116121fe57829003601f168201915b505050505090508073d816c20e28cc704028c475108f4dc535e237ebd96339c27bd49091600261224a85612d4b565b6040518463ffffffff1660e01b81526004016122689392919061406d565b600060405180830381865af4158015612285573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906122ae91906140ab565b9050828173d816c20e28cc704028c475108f4dc535e237ebd9638e7e34d790916040518263ffffffff1660e01b81526004016122ea91906135ce565b600060405180830381865af4158015612307573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906123309190613d2e565b6040516020016123419291906140f4565b604051602081830303815290604052915050919050565b60008060006123679190612df0565b5b8151811080156123b157506123af6040518060200160405280600081525083838151811061239957612398613e32565b5b6020026020010151612c5490919063ffffffff16565b155b1561241d5760008282806123c490613f05565b9350815181106123d7576123d6613e32565b5b6020026020010151908060018154018082558091505060019003906000526020600020016000909190919091509080519060200190612417929190612e11565b50612368565b5050565b6060600061242d6120a2565b905060008573ffffffffffffffffffffffffffffffffffffffff1663f3f8d4e3836040518263ffffffff1660e01b815260040161246a9190614118565b602060405180830381865afa158015612487573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ab9190614031565b90506000826040516020016124c09190613562565b60405160208183030381529060405280519060200120905060008673ffffffffffffffffffffffffffffffffffffffff1663402a652a856040518263ffffffff1660e01b81526004016125139190614118565b602060405180830381865afa158015612530573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125549190613b93565b90506125e98785805461256690613491565b80601f016020809104026020016040519081016040528092919081815260200182805461259290613491565b80156125df5780601f106125b4576101008083540402835291602001916125df565b820191906000526020600020905b8154815290600101906020018083116125c257829003601f168201915b5050505050612d56565b156127cd576000865160f01b9050600061268c8987805461260990613491565b80601f016020809104026020016040519081016040528092919081815260200182805461263590613491565b80156126825780601f1061265757610100808354040283529160200191612682565b820191906000526020600020905b81548152906001019060200180831161266557829003601f168201915b5050505050612d6c565b905087731c407cdd4975532bb5f3f614fb3b48478f597f4963e004139690916000846040518463ffffffff1660e01b81526004016126cc93929190614149565b600060405180830381865af41580156126e9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906127129190613d2e565b8289731c407cdd4975532bb5f3f614fb3b48478f597f4963e0041396909160028661273d9190614187565b8d516040518463ffffffff1660e01b815260040161275d939291906141dd565b600060405180830381865af415801561277a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906127a39190613d2e565b6040516020016127b59392919061421b565b60405160208183030381529060405296505050612c49565b8380546127d990613491565b80601f016020809104026020016040519081016040528092919081815260200182805461280590613491565b80156128525780601f1061282757610100808354040283529160200191612852565b820191906000526020600020905b81548152906001019060200180831161283557829003601f168201915b505050505073d816c20e28cc704028c475108f4dc535e237ebd963fe4f41c890916040518263ffffffff1660e01b815260040161288f91906135ce565b602060405180830381865af41580156128ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d09190613b93565b806128d85750805b15612982578773ffffffffffffffffffffffffffffffffffffffff1663f3f8d4e36040518163ffffffff1660e01b81526004016129149061429c565b602060405180830381865afa158015612931573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129559190614031565b925085838360405160200161296c939291906142bc565b6040516020818303038152906040529450612c48565b600060f81b837effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415612a0c57836040516020016129c1919061438d565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a0391906143ba565b60405180910390fd5b8583604051602001612a1f929190613880565b60405160208183030381529060405294508773ffffffffffffffffffffffffffffffffffffffff16633cb9ceff856040518263ffffffff1660e01b8152600401612a699190614118565b602060405180830381865afa158015612a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aaa9190614408565b9150600060e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612c47576000803073ffffffffffffffffffffffffffffffffffffffff1684888c8c604051602401612b0693929190614435565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051612b709190614473565b600060405180830381855af49150503d8060008114612bab576040519150601f19603f3d011682016040523d82523d6000602084013e612bb0565b606091505b5091509150816040518060400160405280600481526020017f505253310000000000000000000000000000000000000000000000000000000081525090612c2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c2491906143ba565b60405180910390fd5b5080806020019051810190612c429190613d2e565b965050505b5b5b505050509392505050565b600081604051602001612c679190613b1c565b6040516020818303038152906040528051906020012083604051602001612c8e9190613b1c565b6040516020818303038152906040528051906020012014905092915050565b60608282604051602001612cc292919061448a565b604051602081830303815290604052905092915050565b8273ffffffffffffffffffffffffffffffffffffffff1663c0a00cda83836040518363ffffffff1660e01b8152600401612d149291906144bd565b600060405180830381600087803b158015612d2e57600080fd5b505af1158015612d42573d6000803e3d6000fd5b50505050505050565b600081519050919050565b600080612d638484612d6c565b11905092915050565b60008273ffffffffffffffffffffffffffffffffffffffff16635981f3db836040518263ffffffff1660e01b8152600401612da791906143ba565b602060405180830381865afa158015612dc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612de89190613626565b905092915050565b5080546000825590600052602060002090810190612e0e9190612e97565b50565b828054612e1d90613491565b90600052602060002090601f016020900481019282612e3f5760008555612e86565b82601f10612e5857805160ff1916838001178555612e86565b82800160010185558215612e86579182015b82811115612e85578251825591602001919060010190612e6a565b5b509050612e939190612ebb565b5090565b5b80821115612eb75760008181612eae9190612ed8565b50600101612e98565b5090565b5b80821115612ed4576000816000905550600101612ebc565b5090565b508054612ee490613491565b6000825580601f10612ef65750612f15565b601f016020900490600052602060002090810190612f149190612ebb565b5b50565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f7f82612f36565b810181811067ffffffffffffffff82111715612f9e57612f9d612f47565b5b80604052505050565b6000612fb1612f18565b9050612fbd8282612f76565b919050565b600067ffffffffffffffff821115612fdd57612fdc612f47565b5b612fe682612f36565b9050602081019050919050565b82818337600083830152505050565b600061301561301084612fc2565b612fa7565b90508281526020810184848401111561303157613030612f31565b5b61303c848285612ff3565b509392505050565b600082601f83011261305957613058612f2c565b5b8135613069848260208601613002565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061309d82613072565b9050919050565b6130ad81613092565b81146130b857600080fd5b50565b6000813590506130ca816130a4565b92915050565b6000806000606084860312156130e9576130e8612f22565b5b600084013567ffffffffffffffff81111561310757613106612f27565b5b61311386828701613044565b9350506020613124868287016130bb565b9250506040613135868287016130bb565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b60005b8381101561317957808201518184015260208101905061315e565b83811115613188576000848401525b50505050565b60006131998261313f565b6131a3818561314a565b93506131b381856020860161315b565b6131bc81612f36565b840191505092915050565b600060208201905081810360008301526131e1818461318e565b905092915050565b600067ffffffffffffffff82111561320457613203612f47565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff82111561323557613234612f47565b5b61323e82612f36565b9050602081019050919050565b600061325e6132598461321a565b612fa7565b90508281526020810184848401111561327a57613279612f31565b5b613285848285612ff3565b509392505050565b600082601f8301126132a2576132a1612f2c565b5b81356132b284826020860161324b565b91505092915050565b60006132ce6132c9846131e9565b612fa7565b905080838252602082019050602084028301858111156132f1576132f0613215565b5b835b8181101561333857803567ffffffffffffffff81111561331657613315612f2c565b5b808601613323898261328d565b855260208501945050506020810190506132f3565b5050509392505050565b600082601f83011261335757613356612f2c565b5b81356133678482602086016132bb565b91505092915050565b60008060006060848603121561338957613388612f22565b5b6000613397868287016130bb565b93505060206133a8868287016130bb565b925050604084013567ffffffffffffffff8111156133c9576133c8612f27565b5b6133d586828701613342565b9150509250925092565b600080600080608085870312156133f9576133f8612f22565b5b6000613407878288016130bb565b9450506020613418878288016130bb565b9350506040613429878288016130bb565b925050606085013567ffffffffffffffff81111561344a57613449612f27565b5b6134568782880161328d565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806134a957607f821691505b602082108114156134bd576134bc613462565b5b50919050565b600081905092915050565b60008190508160005260206000209050919050565b600081546134f081613491565b6134fa81866134c3565b94506001821660008114613515576001811461352657613559565b60ff19831686528186019350613559565b61352f856134ce565b60005b8381101561355157815481890152600182019150602081019050613532565b838801955050505b50505092915050565b600061356e82846134e3565b915081905092915050565b600081519050919050565b600082825260208201905092915050565b60006135a082613579565b6135aa8185613584565b93506135ba81856020860161315b565b6135c381612f36565b840191505092915050565b600060208201905081810360008301526135e88184613595565b905092915050565b6000819050919050565b613603816135f0565b811461360e57600080fd5b50565b600081519050613620816135fa565b92915050565b60006020828403121561363c5761363b612f22565b5b600061364a84828501613611565b91505092915050565b600081905092915050565b60006136698261313f565b6136738185613653565b935061368381856020860161315b565b80840191505092915050565b6000819050919050565b6000819050919050565b6136b46136af8261368f565b613699565b82525050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b6137016136fc826136ba565b6136e6565b82525050565b6000613713828661365e565b915061371f82856136a3565b60208201915061372f82846136f0565b600482019150819050949350505050565b600061374c828561365e565b915061375882846136a3565b6020820191508190509392505050565b6000819050919050565b6000819050919050565b600061379761379261378d84613768565b613772565b6135f0565b9050919050565b6137a78161377c565b82525050565b60006020820190506137c2600083018461379e565b92915050565b60006137d382613092565b9050919050565b6137e3816137c8565b81146137ee57600080fd5b50565b600081519050613800816137da565b92915050565b60006020828403121561381c5761381b612f22565b5b600061382a848285016137f1565b91505092915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b61387a61387582613833565b61385f565b82525050565b600061388c828561365e565b91506138988284613869565b6001820191508190509392505050565b6138b181613092565b82525050565b600082825260208201905092915050565b60006138d382613579565b6138dd81856138b7565b93506138ed81856020860161315b565b6138f681612f36565b840191505092915050565b600060408201905061391660008301856138a8565b818103602083015261392881846138c8565b90509392505050565b600061394461393f8461321a565b612fa7565b9050828152602081018484840111156139605761395f612f31565b5b61396b84828561315b565b509392505050565b600082601f83011261398857613987612f2c565b5b8151613998848260208601613931565b91505092915050565b60006139b46139af846131e9565b612fa7565b905080838252602082019050602084028301858111156139d7576139d6613215565b5b835b81811015613a1e57805167ffffffffffffffff8111156139fc576139fb612f2c565b5b808601613a098982613973565b855260208501945050506020810190506139d9565b5050509392505050565b600082601f830112613a3d57613a3c612f2c565b5b8151613a4d8482602086016139a1565b91505092915050565b600060208284031215613a6c57613a6b612f22565b5b600082015167ffffffffffffffff811115613a8a57613a89612f27565b5b613a9684828501613a28565b91505092915050565b60006060820190508181036000830152613ab981866138c8565b90508181036020830152613acd81856138c8565b90508181036040830152613ae181846138c8565b9050949350505050565b6000613af682613579565b613b0081856134c3565b9350613b1081856020860161315b565b80840191505092915050565b6000613b288284613aeb565b915081905092915050565b6000613b3f828561365e565b9150613b4b82846136f0565b6004820191508190509392505050565b60008115159050919050565b613b7081613b5b565b8114613b7b57600080fd5b50565b600081519050613b8d81613b67565b92915050565b600060208284031215613ba957613ba8612f22565b5b6000613bb784828501613b7e565b91505092915050565b600082825260208201905092915050565b6000613bdc8261313f565b613be68185613bc0565b9350613bf681856020860161315b565b613bff81612f36565b840191505092915050565b6000819050919050565b6000613c2f613c2a613c2584613c0a565b613772565b6135f0565b9050919050565b613c3f81613c14565b82525050565b6000819050919050565b6000613c6a613c65613c6084613c45565b613772565b6135f0565b9050919050565b613c7a81613c4f565b82525050565b60006060820190508181036000830152613c9a8186613bd1565b9050613ca96020830185613c36565b613cb66040830184613c71565b949350505050565b6000613cd1613ccc84612fc2565b612fa7565b905082815260208101848484011115613ced57613cec612f31565b5b613cf884828561315b565b509392505050565b600082601f830112613d1557613d14612f2c565b5b8151613d25848260208601613cbe565b91505092915050565b600060208284031215613d4457613d43612f22565b5b600082015167ffffffffffffffff811115613d6257613d61612f27565b5b613d6e84828501613d00565b91505092915050565b60006020820190508181036000830152613d918184613bd1565b905092915050565b6000819050602082019050919050565b6000613db5825161368f565b80915050919050565b600082821b905092915050565b6000613dd68261313f565b82613de084613d99565b9050613deb81613da9565b92506020821015613e2b57613e267fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802613dbe565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffff00000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b613ea8613ea382613e61565b613e8d565b82525050565b6000613eba828561365e565b9150613ec68284613e97565b6002820191508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613f10826135f0565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613f4357613f42613ed6565b5b600182019050919050565b60008154613f5b81613491565b613f6581866138b7565b94506001821660008114613f805760018114613f9257613fc5565b60ff1983168652602086019350613fc5565b613f9b856134ce565b60005b83811015613fbd57815481890152600182019150602081019050613f9e565b808801955050505b50505092915050565b60006040820190508181036000830152613fe881856138c8565b90508181036020830152613ffc8184613f4e565b90509392505050565b61400e81613833565b811461401957600080fd5b50565b60008151905061402b81614005565b92915050565b60006020828403121561404757614046612f22565b5b60006140558482850161401c565b91505092915050565b614067816135f0565b82525050565b600060608201905081810360008301526140878186613595565b90506140966020830185613c36565b6140a3604083018461405e565b949350505050565b6000602082840312156140c1576140c0612f22565b5b600082015167ffffffffffffffff8111156140df576140de612f27565b5b6140eb84828501613973565b91505092915050565b6000614100828561365e565b915061410c828461365e565b91508190509392505050565b600060208201905081810360008301526141328184613f4e565b905092915050565b6141438161377c565b82525050565b600060608201905081810360008301526141638186613bd1565b9050614172602083018561413a565b61417f604083018461405e565b949350505050565b6000614192826135f0565b915061419d836135f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156141d2576141d1613ed6565b5b828201905092915050565b600060608201905081810360008301526141f78186613bd1565b9050614206602083018561405e565b614213604083018461405e565b949350505050565b6000614227828661365e565b91506142338285613e97565b600282019150614243828461365e565b9150819050949350505050565b7f7661720000000000000000000000000000000000000000000000000000000000600082015250565b60006142866003836138b7565b915061429182614250565b602082019050919050565b600060208201905081810360008301526142b581614279565b9050919050565b60006142c8828661365e565b91506142d48285613869565b6001820191506142e482846136f0565b600482019150819050949350505050565b7f5061727365723a20220000000000000000000000000000000000000000000000600082015250565b600061432b6009836134c3565b9150614336826142f5565b600982019050919050565b7f2220636f6d6d616e6420697320756e6b6e6f776e000000000000000000000000600082015250565b60006143776014836134c3565b915061438282614341565b601482019050919050565b60006143988261431e565b91506143a482846134e3565b91506143af8261436a565b915081905092915050565b600060208201905081810360008301526143d481846138c8565b905092915050565b6143e5816136ba565b81146143f057600080fd5b50565b600081519050614402816143dc565b92915050565b60006020828403121561441e5761441d612f22565b5b600061442c848285016143f3565b91505092915050565b6000606082019050818103600083015261444f818661318e565b905061445e60208301856138a8565b61446b60408301846138a8565b949350505050565b600061447f828461365e565b915081905092915050565b60006144968285613aeb565b91506144a28284613aeb565b91508190509392505050565b6144b7816135f0565b82525050565b600060408201905081810360008301526144d781856138c8565b90506144e660208301846144ae565b939250505056fea26469706673582212201e0b8ec899002850ccacf7b3432f0c6e7ccb7bef54a6e0ec209708e1b0ae02f464736f6c634300080b0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101845760003560e01c806390d95d80116100d9578063c45e3e5011610087578063c45e3e5014610551578063c92b45e114610581578063cbfc5ad4146105b1578063cedba5f1146105e1578063dc19dabd14610611578063f5a4363e14610641578063f7edbb701461067157610184565b806390d95d80146104155780639609ebb3146104455780639714a18214610461578063997f430614610491578063b9c34291146104c1578063b9dd4c83146104f1578063bfd5b4451461052157610184565b80635887e21b116101365780635887e21b146102d957806368bf5659146103095780636960e80b14610339578063861826411461036957806386b8d4e81461039957806389995a9e146103c95780638bc0a7a7146103e557610184565b8063021d30be1461018957806303dc1cee146101b957806305feb51f146101e95780630f47ec74146102195780632909fb3e1461024957806353edd023146102795780635694922f146102a9575b600080fd5b6101a3600480360381019061019e91906130d0565b6106a1565b6040516101b091906131c7565b60405180910390f35b6101d360048036038101906101ce91906130d0565b6106b5565b6040516101e091906131c7565b60405180910390f35b61020360048036038101906101fe91906130d0565b6106dd565b60405161021091906131c7565b60405180910390f35b610233600480360381019061022e91906130d0565b610851565b60405161024091906131c7565b60405180910390f35b610263600480360381019061025e91906130d0565b610865565b60405161027091906131c7565b60405180910390f35b610293600480360381019061028e91906130d0565b6109a4565b6040516102a091906131c7565b60405180910390f35b6102c360048036038101906102be91906130d0565b6109b8565b6040516102d091906131c7565b60405180910390f35b6102f360048036038101906102ee91906130d0565b6109e5565b60405161030091906131c7565b60405180910390f35b610323600480360381019061031e91906130d0565b610a44565b60405161033091906131c7565b60405180910390f35b610353600480360381019061034e91906130d0565b610a66565b60405161036091906131c7565b60405180910390f35b610383600480360381019061037e91906130d0565b610abc565b60405161039091906131c7565b60405180910390f35b6103b360048036038101906103ae91906130d0565b610b1d565b6040516103c091906131c7565b60405180910390f35b6103e360048036038101906103de9190613370565b610b3c565b005b6103ff60048036038101906103fa91906130d0565b610d89565b60405161040c91906131c7565b60405180910390f35b61042f600480360381019061042a91906130d0565b610ea4565b60405161043c91906131c7565b60405180910390f35b61045f600480360381019061045a91906133df565b610eb8565b005b61047b600480360381019061047691906130d0565b610f4f565b60405161048891906131c7565b60405180910390f35b6104ab60048036038101906104a691906130d0565b6117a5565b6040516104b891906131c7565b60405180910390f35b6104db60048036038101906104d691906130d0565b6117dd565b6040516104e891906131c7565b60405180910390f35b61050b600480360381019061050691906130d0565b6118aa565b60405161051891906131c7565b60405180910390f35b61053b600480360381019061053691906130d0565b611ce8565b60405161054891906131c7565b60405180910390f35b61056b600480360381019061056691906130d0565b611d10565b60405161057891906131c7565b60405180910390f35b61059b600480360381019061059691906130d0565b611d3a565b6040516105a891906131c7565b60405180910390f35b6105cb60048036038101906105c691906130d0565b611d5c565b6040516105d891906131c7565b60405180910390f35b6105fb60048036038101906105f691906130d0565b611ef9565b60405161060891906131c7565b60405180910390f35b61062b600480360381019061062691906130d0565b611fc6565b60405161063891906131c7565b60405180910390f35b61065b600480360381019061065691906130d0565b611ff0565b60405161066891906131c7565b60405180910390f35b61068b600480360381019061068691906130d0565b61200f565b60405161069891906131c7565b60405180910390f35b60606106ac84612044565b90509392505050565b60606106c084612044565b90506106ca6120a2565b506106d481612044565b90509392505050565b606060006106e96120a2565b80546106f490613491565b80601f016020809104026020016040519081016040528092919081815260200182805461072090613491565b801561076d5780601f106107425761010080835404028352916020019161076d565b820191906000526020600020905b81548152906001019060200180831161075057829003601f168201915b50505050509050600061077e6120a2565b60405160200161078e9190613562565b604051602081830303815290604052805190602001209050858273d816c20e28cc704028c475108f4dc535e237ebd96370121b7190916040518263ffffffff1660e01b81526004016107e091906135ce565b602060405180830381865af41580156107fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108219190613626565b60001b8260405160200161083793929190613707565b604051602081830303815290604052925050509392505050565b606061085c84612044565b90509392505050565b606060006108716120a2565b805461087c90613491565b80601f01602080910402602001604051908101604052809291908181526020018280546108a890613491565b80156108f55780601f106108ca576101008083540402835291602001916108f5565b820191906000526020600020905b8154815290600101906020018083116108d857829003601f168201915b505050505073d816c20e28cc704028c475108f4dc535e237ebd96370121b7190916040518263ffffffff1660e01b815260040161093291906135ce565b602060405180830381865af415801561094f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109739190613626565b9050848160001b60405160200161098b929190613740565b6040516020818303038152906040529150509392505050565b60606109af84612044565b90509392505050565b60606109c384612044565b90506109ce81612044565b90506109dc81600080610865565b90509392505050565b6060610a2784846040518060400160405280600881526020017f636f6d706f756e640000000000000000000000000000000000000000000000008152506120dc565b9050610a316120a2565b50610a3b81612044565b90509392505050565b6060610a4f84612044565b9050610a5d81600080610d89565b90509392505050565b6060610aa884846040518060400160405280600a81526020017f6465636c617265417272000000000000000000000000000000000000000000008152506120dc565b9050610ab381612044565b90509392505050565b6060610afe84846040518060400160405280600a81526020017f6c6f616452656d6f7465000000000000000000000000000000000000000000008152506120dc565b9050610b0981612044565b9050610b148161218b565b90509392505050565b6060610b2884612044565b9050610b3381612044565b90509392505050565b60006001819055506060808373ffffffffffffffffffffffffffffffffffffffff1663bcf80c9d836040518263ffffffff1660e01b8152600401610b8091906131c7565b600060405180830381600087803b158015610b9a57600080fd5b505af1158015610bae573d6000803e3d6000fd5b50505050610bbb83612358565b8373ffffffffffffffffffffffffffffffffffffffff1663f26c917860006040518263ffffffff1660e01b8152600401610bf591906137ad565b600060405180830381600087803b158015610c0f57600080fd5b505af1158015610c23573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff1663138ef1516040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c969190613806565b73ffffffffffffffffffffffffffffffffffffffff166352efea6e6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610cdd57600080fd5b505af1158015610cf1573d6000803e3d6000fd5b505050505b6000805490506001541015610d1757610d10858583612421565b9050610cf6565b8373ffffffffffffffffffffffffffffffffffffffff1663bcf80c9d826040518263ffffffff1660e01b8152600401610d5091906131c7565b600060405180830381600087803b158015610d6a57600080fd5b505af1158015610d7e573d6000803e3d6000fd5b505050505050505050565b60606000610e656040518060400160405280600481526020017f7472756500000000000000000000000000000000000000000000000000000000815250610dce6120a2565b8054610dd990613491565b80601f0160208091040260200160405190810160405280929190818152602001828054610e0590613491565b8015610e525780601f10610e2757610100808354040283529160200191610e52565b820191906000526020600020905b815481529060010190602001808311610e3557829003601f168201915b5050505050612c5490919063ffffffff16565b610e70576000610e73565b60015b60f81b90508481604051602001610e8b929190613880565b6040516020818303038152906040529150509392505050565b6060610eaf84612044565b90509392505050565b60008473ffffffffffffffffffffffffffffffffffffffff16630411de8885846040518363ffffffff1660e01b8152600401610ef5929190613901565b600060405180830381865afa158015610f12573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610f3b9190613a56565b9050610f48848483610b3c565b5050505050565b60606000610f5b6120a2565b8054610f6690613491565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9290613491565b8015610fdf5780601f10610fb457610100808354040283529160200191610fdf565b820191906000526020600020905b815481529060010190602001808311610fc257829003601f168201915b505050505090508491505b6000610ff46120a2565b8054610fff90613491565b80601f016020809104026020016040519081016040528092919081815260200182805461102b90613491565b80156110785780601f1061104d57610100808354040283529160200191611078565b820191906000526020600020905b81548152906001019060200180831161105b57829003601f168201915b5050505050905060006110db826110cd6040518060400160405280600181526020017f2e0000000000000000000000000000000000000000000000000000000000000081525086612cad90919063ffffffff16565b612cad90919063ffffffff16565b90508473ffffffffffffffffffffffffffffffffffffffff1663d598989e8484846040518463ffffffff1660e01b815260040161111a93929190613a9f565b600060405180830381600087803b15801561113457600080fd5b505af1158015611148573d6000803e3d6000fd5b50505050838160405160200161115e9190613b1c565b60405160208183030381529060405280519060200120604051602001611185929190613b33565b604051602081830303815290604052935060006111a06120a2565b80546111ab90613491565b80601f01602080910402602001604051908101604052809291908181526020018280546111d790613491565b80156112245780601f106111f957610100808354040283529160200191611224565b820191906000526020600020905b81548152906001019060200180831161120757829003601f168201915b505050505090508073d816c20e28cc704028c475108f4dc535e237ebd9634863d3e190916040518263ffffffff1660e01b815260040161126491906135ce565b602060405180830381865af4158015611281573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a59190613b93565b156113e457600081731c407cdd4975532bb5f3f614fb3b48478f597f4963e004139690916002602a6040518463ffffffff1660e01b81526004016112eb93929190613c80565b600060405180830381865af4158015611308573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906113319190613d2e565b90508581731c407cdd4975532bb5f3f614fb3b48478f597f49632c16769b90916040518263ffffffff1660e01b815260040161136d9190613d77565b600060405180830381865af415801561138a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906113b39190613d2e565b6113bc90613dcb565b6040516020016113cd929190613740565b60405160208183030381529060405295505061169a565b8073d816c20e28cc704028c475108f4dc535e237ebd963dba27b1c90916040518263ffffffff1660e01b815260040161141d91906135ce565b602060405180830381865af415801561143a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145e9190613b93565b1561150857848173d816c20e28cc704028c475108f4dc535e237ebd96370121b7190916040518263ffffffff1660e01b815260040161149d91906135ce565b602060405180830381865af41580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de9190613626565b60001b6040516020016114f2929190613740565b6040516020818303038152906040529450611699565b6115506040518060400160405280600481526020017f766f74650000000000000000000000000000000000000000000000000000000081525084612c5490919063ffffffff16565b80156115a0575061159f6040518060400160405280600381526020017f594553000000000000000000000000000000000000000000000000000000000081525082612c5490919063ffffffff16565b5b156115d25784600160001b6040516020016115bc929190613740565b6040516020818303038152906040529450611698565b61161a6040518060400160405280600481526020017f766f74650000000000000000000000000000000000000000000000000000000081525084612c5490919063ffffffff16565b801561166a57506116696040518060400160405280600281526020017f4e4f00000000000000000000000000000000000000000000000000000000000081525082612c5490919063ffffffff16565b5b1561169757846000801b604051602001611685929190613740565b60405160208183030381529060405294505b5b5b5b50505061178d6040518060400160405280600981526020017f656e6453747275637400000000000000000000000000000000000000000000008152506000600154815481106116ec576116eb613e32565b5b90600052602060002001805461170190613491565b80601f016020809104026020016040519081016040528092919081815260200182805461172d90613491565b801561177a5780601f1061174f5761010080835404028352916020019161177a565b820191906000526020600020905b81548152906001019060200180831161175d57829003601f168201915b5050505050612c5490919063ffffffff16565b15610fea5761179b82612044565b9150509392505050565b60606117b084612044565b90506117bb81612044565b90506117c681612044565b90506117d481600080610865565b90509392505050565b606061187b826117eb6120a2565b80546117f690613491565b80601f016020809104026020016040519081016040528092919081815260200182805461182290613491565b801561186f5780601f106118445761010080835404028352916020019161186f565b820191906000526020600020905b81548152906001019060200180831161185257829003601f168201915b50505050508651612cd9565b83600060f01b604051602001611892929190613eae565b60405160208183030381529060405290509392505050565b606060006118b66120a2565b80546118c190613491565b80601f01602080910402602001604051908101604052809291908181526020018280546118ed90613491565b801561193a5780601f1061190f5761010080835404028352916020019161193a565b820191906000526020600020905b81548152906001019060200180831161191d57829003601f168201915b50505050509050600061194b6120a2565b60405160200161195b9190613562565b6040516020818303038152906040528051906020012090508173d816c20e28cc704028c475108f4dc535e237ebd9634863d3e190916040518263ffffffff1660e01b81526004016119ac91906135ce565b602060405180830381865af41580156119c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ed9190613b93565b15611b2c57600082731c407cdd4975532bb5f3f614fb3b48478f597f4963e004139690916002602a6040518463ffffffff1660e01b8152600401611a3393929190613c80565b600060405180830381865af4158015611a50573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611a799190613d2e565b90508681731c407cdd4975532bb5f3f614fb3b48478f597f49632c16769b90916040518263ffffffff1660e01b8152600401611ab59190613d77565b600060405180830381865af4158015611ad2573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611afb9190613d2e565b611b0490613dcb565b604051602001611b15929190613740565b604051602081830303815290604052935050611cbb565b8173d816c20e28cc704028c475108f4dc535e237ebd963dba27b1c90916040518263ffffffff1660e01b8152600401611b6591906135ce565b602060405180830381865af4158015611b82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba69190613b93565b15611c5057858273d816c20e28cc704028c475108f4dc535e237ebd96370121b7190916040518263ffffffff1660e01b8152600401611be591906135ce565b602060405180830381865af4158015611c02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c269190613626565b60001b604051602001611c3a929190613740565b6040516020818303038152906040529250611cba565b8582604051602001611c629190613b1c565b604051602081830303815290604052805190602001207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916604051602001611ca8929190613740565b60405160208183030381529060405292505b5b8281604051602001611cce929190613b33565b604051602081830303815290604052925050509392505050565b6060611cf384612044565b9050611cfd6120a2565b50611d0781612044565b90509392505050565b6060611d1b84612044565b9050611d2681612044565b9050611d3181612044565b90509392505050565b6060611d4584612044565b9050611d5381600080610865565b90509392505050565b60606000611d686120a2565b8054611d7390613491565b80601f0160208091040260200160405190810160405280929190818152602001828054611d9f90613491565b8015611dec5780601f10611dc157610100808354040283529160200191611dec565b820191906000526020600020905b815481529060010190602001808311611dcf57829003601f168201915b505050505090506000611dfd6120a2565b8054611e0890613491565b80601f0160208091040260200160405190810160405280929190818152602001828054611e3490613491565b8015611e815780601f10611e5657610100808354040283529160200191611e81565b820191906000526020600020905b815481529060010190602001808311611e6457829003601f168201915b50505050509050611e9484838851612cd9565b85600060f01b604051602001611eab929190613eae565b6040516020818303038152906040529250611ec884828551612cd9565b82600060f01b604051602001611edf929190613eae565b604051602081830303815290604052925050509392505050565b6060611f9782611f076120a2565b8054611f1290613491565b80601f0160208091040260200160405190810160405280929190818152602001828054611f3e90613491565b8015611f8b5780601f10611f6057610100808354040283529160200191611f8b565b820191906000526020600020905b815481529060010190602001808311611f6e57829003601f168201915b50505050508651612cd9565b83600060f01b604051602001611fae929190613eae565b60405160208183030381529060405290509392505050565b6060611fd184612044565b9050611fdc81612044565b9050611fe781612044565b90509392505050565b6060611ffb84612044565b905061200681612044565b90509392505050565b606061201a84612044565b905061202581612044565b905061203081612044565b905061203b81612044565b90509392505050565b606060006120506120a2565b6040516020016120609190613562565b604051602081830303815290604052805190602001209050828160405160200161208b929190613b33565b604051602081830303815290604052915050919050565b600080600160008154809291906120b890613f05565b91905055815481106120cd576120cc613e32565b5b90600052602060002001905090565b6060838373ffffffffffffffffffffffffffffffffffffffff16635bf3e5d7846121046120a2565b6040518363ffffffff1660e01b8152600401612121929190613fce565b602060405180830381865afa15801561213e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121629190614031565b604051602001612173929190613880565b60405160208183030381529060405290509392505050565b606060006121976120a2565b80546121a290613491565b80601f01602080910402602001604051908101604052809291908181526020018280546121ce90613491565b801561221b5780601f106121f05761010080835404028352916020019161221b565b820191906000526020600020905b8154815290600101906020018083116121fe57829003601f168201915b505050505090508073d816c20e28cc704028c475108f4dc535e237ebd96339c27bd49091600261224a85612d4b565b6040518463ffffffff1660e01b81526004016122689392919061406d565b600060405180830381865af4158015612285573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906122ae91906140ab565b9050828173d816c20e28cc704028c475108f4dc535e237ebd9638e7e34d790916040518263ffffffff1660e01b81526004016122ea91906135ce565b600060405180830381865af4158015612307573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906123309190613d2e565b6040516020016123419291906140f4565b604051602081830303815290604052915050919050565b60008060006123679190612df0565b5b8151811080156123b157506123af6040518060200160405280600081525083838151811061239957612398613e32565b5b6020026020010151612c5490919063ffffffff16565b155b1561241d5760008282806123c490613f05565b9350815181106123d7576123d6613e32565b5b6020026020010151908060018154018082558091505060019003906000526020600020016000909190919091509080519060200190612417929190612e11565b50612368565b5050565b6060600061242d6120a2565b905060008573ffffffffffffffffffffffffffffffffffffffff1663f3f8d4e3836040518263ffffffff1660e01b815260040161246a9190614118565b602060405180830381865afa158015612487573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ab9190614031565b90506000826040516020016124c09190613562565b60405160208183030381529060405280519060200120905060008673ffffffffffffffffffffffffffffffffffffffff1663402a652a856040518263ffffffff1660e01b81526004016125139190614118565b602060405180830381865afa158015612530573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125549190613b93565b90506125e98785805461256690613491565b80601f016020809104026020016040519081016040528092919081815260200182805461259290613491565b80156125df5780601f106125b4576101008083540402835291602001916125df565b820191906000526020600020905b8154815290600101906020018083116125c257829003601f168201915b5050505050612d56565b156127cd576000865160f01b9050600061268c8987805461260990613491565b80601f016020809104026020016040519081016040528092919081815260200182805461263590613491565b80156126825780601f1061265757610100808354040283529160200191612682565b820191906000526020600020905b81548152906001019060200180831161266557829003601f168201915b5050505050612d6c565b905087731c407cdd4975532bb5f3f614fb3b48478f597f4963e004139690916000846040518463ffffffff1660e01b81526004016126cc93929190614149565b600060405180830381865af41580156126e9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906127129190613d2e565b8289731c407cdd4975532bb5f3f614fb3b48478f597f4963e0041396909160028661273d9190614187565b8d516040518463ffffffff1660e01b815260040161275d939291906141dd565b600060405180830381865af415801561277a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906127a39190613d2e565b6040516020016127b59392919061421b565b60405160208183030381529060405296505050612c49565b8380546127d990613491565b80601f016020809104026020016040519081016040528092919081815260200182805461280590613491565b80156128525780601f1061282757610100808354040283529160200191612852565b820191906000526020600020905b81548152906001019060200180831161283557829003601f168201915b505050505073d816c20e28cc704028c475108f4dc535e237ebd963fe4f41c890916040518263ffffffff1660e01b815260040161288f91906135ce565b602060405180830381865af41580156128ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d09190613b93565b806128d85750805b15612982578773ffffffffffffffffffffffffffffffffffffffff1663f3f8d4e36040518163ffffffff1660e01b81526004016129149061429c565b602060405180830381865afa158015612931573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129559190614031565b925085838360405160200161296c939291906142bc565b6040516020818303038152906040529450612c48565b600060f81b837effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415612a0c57836040516020016129c1919061438d565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a0391906143ba565b60405180910390fd5b8583604051602001612a1f929190613880565b60405160208183030381529060405294508773ffffffffffffffffffffffffffffffffffffffff16633cb9ceff856040518263ffffffff1660e01b8152600401612a699190614118565b602060405180830381865afa158015612a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aaa9190614408565b9150600060e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612c47576000803073ffffffffffffffffffffffffffffffffffffffff1684888c8c604051602401612b0693929190614435565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051612b709190614473565b600060405180830381855af49150503d8060008114612bab576040519150601f19603f3d011682016040523d82523d6000602084013e612bb0565b606091505b5091509150816040518060400160405280600481526020017f505253310000000000000000000000000000000000000000000000000000000081525090612c2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c2491906143ba565b60405180910390fd5b5080806020019051810190612c429190613d2e565b965050505b5b5b505050509392505050565b600081604051602001612c679190613b1c565b6040516020818303038152906040528051906020012083604051602001612c8e9190613b1c565b6040516020818303038152906040528051906020012014905092915050565b60608282604051602001612cc292919061448a565b604051602081830303815290604052905092915050565b8273ffffffffffffffffffffffffffffffffffffffff1663c0a00cda83836040518363ffffffff1660e01b8152600401612d149291906144bd565b600060405180830381600087803b158015612d2e57600080fd5b505af1158015612d42573d6000803e3d6000fd5b50505050505050565b600081519050919050565b600080612d638484612d6c565b11905092915050565b60008273ffffffffffffffffffffffffffffffffffffffff16635981f3db836040518263ffffffff1660e01b8152600401612da791906143ba565b602060405180830381865afa158015612dc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612de89190613626565b905092915050565b5080546000825590600052602060002090810190612e0e9190612e97565b50565b828054612e1d90613491565b90600052602060002090601f016020900481019282612e3f5760008555612e86565b82601f10612e5857805160ff1916838001178555612e86565b82800160010185558215612e86579182015b82811115612e85578251825591602001919060010190612e6a565b5b509050612e939190612ebb565b5090565b5b80821115612eb75760008181612eae9190612ed8565b50600101612e98565b5090565b5b80821115612ed4576000816000905550600101612ebc565b5090565b508054612ee490613491565b6000825580601f10612ef65750612f15565b601f016020900490600052602060002090810190612f149190612ebb565b5b50565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f7f82612f36565b810181811067ffffffffffffffff82111715612f9e57612f9d612f47565b5b80604052505050565b6000612fb1612f18565b9050612fbd8282612f76565b919050565b600067ffffffffffffffff821115612fdd57612fdc612f47565b5b612fe682612f36565b9050602081019050919050565b82818337600083830152505050565b600061301561301084612fc2565b612fa7565b90508281526020810184848401111561303157613030612f31565b5b61303c848285612ff3565b509392505050565b600082601f83011261305957613058612f2c565b5b8135613069848260208601613002565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061309d82613072565b9050919050565b6130ad81613092565b81146130b857600080fd5b50565b6000813590506130ca816130a4565b92915050565b6000806000606084860312156130e9576130e8612f22565b5b600084013567ffffffffffffffff81111561310757613106612f27565b5b61311386828701613044565b9350506020613124868287016130bb565b9250506040613135868287016130bb565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b60005b8381101561317957808201518184015260208101905061315e565b83811115613188576000848401525b50505050565b60006131998261313f565b6131a3818561314a565b93506131b381856020860161315b565b6131bc81612f36565b840191505092915050565b600060208201905081810360008301526131e1818461318e565b905092915050565b600067ffffffffffffffff82111561320457613203612f47565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff82111561323557613234612f47565b5b61323e82612f36565b9050602081019050919050565b600061325e6132598461321a565b612fa7565b90508281526020810184848401111561327a57613279612f31565b5b613285848285612ff3565b509392505050565b600082601f8301126132a2576132a1612f2c565b5b81356132b284826020860161324b565b91505092915050565b60006132ce6132c9846131e9565b612fa7565b905080838252602082019050602084028301858111156132f1576132f0613215565b5b835b8181101561333857803567ffffffffffffffff81111561331657613315612f2c565b5b808601613323898261328d565b855260208501945050506020810190506132f3565b5050509392505050565b600082601f83011261335757613356612f2c565b5b81356133678482602086016132bb565b91505092915050565b60008060006060848603121561338957613388612f22565b5b6000613397868287016130bb565b93505060206133a8868287016130bb565b925050604084013567ffffffffffffffff8111156133c9576133c8612f27565b5b6133d586828701613342565b9150509250925092565b600080600080608085870312156133f9576133f8612f22565b5b6000613407878288016130bb565b9450506020613418878288016130bb565b9350506040613429878288016130bb565b925050606085013567ffffffffffffffff81111561344a57613449612f27565b5b6134568782880161328d565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806134a957607f821691505b602082108114156134bd576134bc613462565b5b50919050565b600081905092915050565b60008190508160005260206000209050919050565b600081546134f081613491565b6134fa81866134c3565b94506001821660008114613515576001811461352657613559565b60ff19831686528186019350613559565b61352f856134ce565b60005b8381101561355157815481890152600182019150602081019050613532565b838801955050505b50505092915050565b600061356e82846134e3565b915081905092915050565b600081519050919050565b600082825260208201905092915050565b60006135a082613579565b6135aa8185613584565b93506135ba81856020860161315b565b6135c381612f36565b840191505092915050565b600060208201905081810360008301526135e88184613595565b905092915050565b6000819050919050565b613603816135f0565b811461360e57600080fd5b50565b600081519050613620816135fa565b92915050565b60006020828403121561363c5761363b612f22565b5b600061364a84828501613611565b91505092915050565b600081905092915050565b60006136698261313f565b6136738185613653565b935061368381856020860161315b565b80840191505092915050565b6000819050919050565b6000819050919050565b6136b46136af8261368f565b613699565b82525050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b6137016136fc826136ba565b6136e6565b82525050565b6000613713828661365e565b915061371f82856136a3565b60208201915061372f82846136f0565b600482019150819050949350505050565b600061374c828561365e565b915061375882846136a3565b6020820191508190509392505050565b6000819050919050565b6000819050919050565b600061379761379261378d84613768565b613772565b6135f0565b9050919050565b6137a78161377c565b82525050565b60006020820190506137c2600083018461379e565b92915050565b60006137d382613092565b9050919050565b6137e3816137c8565b81146137ee57600080fd5b50565b600081519050613800816137da565b92915050565b60006020828403121561381c5761381b612f22565b5b600061382a848285016137f1565b91505092915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b61387a61387582613833565b61385f565b82525050565b600061388c828561365e565b91506138988284613869565b6001820191508190509392505050565b6138b181613092565b82525050565b600082825260208201905092915050565b60006138d382613579565b6138dd81856138b7565b93506138ed81856020860161315b565b6138f681612f36565b840191505092915050565b600060408201905061391660008301856138a8565b818103602083015261392881846138c8565b90509392505050565b600061394461393f8461321a565b612fa7565b9050828152602081018484840111156139605761395f612f31565b5b61396b84828561315b565b509392505050565b600082601f83011261398857613987612f2c565b5b8151613998848260208601613931565b91505092915050565b60006139b46139af846131e9565b612fa7565b905080838252602082019050602084028301858111156139d7576139d6613215565b5b835b81811015613a1e57805167ffffffffffffffff8111156139fc576139fb612f2c565b5b808601613a098982613973565b855260208501945050506020810190506139d9565b5050509392505050565b600082601f830112613a3d57613a3c612f2c565b5b8151613a4d8482602086016139a1565b91505092915050565b600060208284031215613a6c57613a6b612f22565b5b600082015167ffffffffffffffff811115613a8a57613a89612f27565b5b613a9684828501613a28565b91505092915050565b60006060820190508181036000830152613ab981866138c8565b90508181036020830152613acd81856138c8565b90508181036040830152613ae181846138c8565b9050949350505050565b6000613af682613579565b613b0081856134c3565b9350613b1081856020860161315b565b80840191505092915050565b6000613b288284613aeb565b915081905092915050565b6000613b3f828561365e565b9150613b4b82846136f0565b6004820191508190509392505050565b60008115159050919050565b613b7081613b5b565b8114613b7b57600080fd5b50565b600081519050613b8d81613b67565b92915050565b600060208284031215613ba957613ba8612f22565b5b6000613bb784828501613b7e565b91505092915050565b600082825260208201905092915050565b6000613bdc8261313f565b613be68185613bc0565b9350613bf681856020860161315b565b613bff81612f36565b840191505092915050565b6000819050919050565b6000613c2f613c2a613c2584613c0a565b613772565b6135f0565b9050919050565b613c3f81613c14565b82525050565b6000819050919050565b6000613c6a613c65613c6084613c45565b613772565b6135f0565b9050919050565b613c7a81613c4f565b82525050565b60006060820190508181036000830152613c9a8186613bd1565b9050613ca96020830185613c36565b613cb66040830184613c71565b949350505050565b6000613cd1613ccc84612fc2565b612fa7565b905082815260208101848484011115613ced57613cec612f31565b5b613cf884828561315b565b509392505050565b600082601f830112613d1557613d14612f2c565b5b8151613d25848260208601613cbe565b91505092915050565b600060208284031215613d4457613d43612f22565b5b600082015167ffffffffffffffff811115613d6257613d61612f27565b5b613d6e84828501613d00565b91505092915050565b60006020820190508181036000830152613d918184613bd1565b905092915050565b6000819050602082019050919050565b6000613db5825161368f565b80915050919050565b600082821b905092915050565b6000613dd68261313f565b82613de084613d99565b9050613deb81613da9565b92506020821015613e2b57613e267fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802613dbe565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffff00000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b613ea8613ea382613e61565b613e8d565b82525050565b6000613eba828561365e565b9150613ec68284613e97565b6002820191508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613f10826135f0565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613f4357613f42613ed6565b5b600182019050919050565b60008154613f5b81613491565b613f6581866138b7565b94506001821660008114613f805760018114613f9257613fc5565b60ff1983168652602086019350613fc5565b613f9b856134ce565b60005b83811015613fbd57815481890152600182019150602081019050613f9e565b808801955050505b50505092915050565b60006040820190508181036000830152613fe881856138c8565b90508181036020830152613ffc8184613f4e565b90509392505050565b61400e81613833565b811461401957600080fd5b50565b60008151905061402b81614005565b92915050565b60006020828403121561404757614046612f22565b5b60006140558482850161401c565b91505092915050565b614067816135f0565b82525050565b600060608201905081810360008301526140878186613595565b90506140966020830185613c36565b6140a3604083018461405e565b949350505050565b6000602082840312156140c1576140c0612f22565b5b600082015167ffffffffffffffff8111156140df576140de612f27565b5b6140eb84828501613973565b91505092915050565b6000614100828561365e565b915061410c828461365e565b91508190509392505050565b600060208201905081810360008301526141328184613f4e565b905092915050565b6141438161377c565b82525050565b600060608201905081810360008301526141638186613bd1565b9050614172602083018561413a565b61417f604083018461405e565b949350505050565b6000614192826135f0565b915061419d836135f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156141d2576141d1613ed6565b5b828201905092915050565b600060608201905081810360008301526141f78186613bd1565b9050614206602083018561405e565b614213604083018461405e565b949350505050565b6000614227828661365e565b91506142338285613e97565b600282019150614243828461365e565b9150819050949350505050565b7f7661720000000000000000000000000000000000000000000000000000000000600082015250565b60006142866003836138b7565b915061429182614250565b602082019050919050565b600060208201905081810360008301526142b581614279565b9050919050565b60006142c8828661365e565b91506142d48285613869565b6001820191506142e482846136f0565b600482019150819050949350505050565b7f5061727365723a20220000000000000000000000000000000000000000000000600082015250565b600061432b6009836134c3565b9150614336826142f5565b600982019050919050565b7f2220636f6d6d616e6420697320756e6b6e6f776e000000000000000000000000600082015250565b60006143776014836134c3565b915061438282614341565b601482019050919050565b60006143988261431e565b91506143a482846134e3565b91506143af8261436a565b915081905092915050565b600060208201905081810360008301526143d481846138c8565b905092915050565b6143e5816136ba565b81146143f057600080fd5b50565b600081519050614402816143dc565b92915050565b60006020828403121561441e5761441d612f22565b5b600061442c848285016143f3565b91505092915050565b6000606082019050818103600083015261444f818661318e565b905061445e60208301856138a8565b61446b60408301846138a8565b949350505050565b600061447f828461365e565b915081905092915050565b60006144968285613aeb565b91506144a28284613aeb565b91508190509392505050565b6144b7816135f0565b82525050565b600060408201905081810360008301526144d781856138c8565b90506144e660208301846144ae565b939250505056fea26469706673582212201e0b8ec899002850ccacf7b3432f0c6e7ccb7bef54a6e0ec209708e1b0ae02f464736f6c634300080b0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.