def run_trigger(new_logs):
    """ Template trigger """
    events = []

    for ev in get_events(new_logs):
        recipient, amount = decode_single('(address,uint256)',
                                          decode_hex(ev.data))

        if amount == 0:
            continue

        contract_name = CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address)
        """ Event doesn't include token address, so if it's not from STRATCOMP,
        I have no idea what it might be.
        """
        reward_token = '[UKNOWN]'
        if ev.address == STRATCOMP:
            reward_token = 'COMP'
        elif ev.address == STRAT3POOL:
            reward_token = 'CRV'

        events.append(
            event_normal("Reward tokens have been collected   💸",
                         "{} {} has been collected by {}\n".format(
                             format_token_human('COMP', amount),
                             reward_token,
                             contract_name,
                         ),
                         log_model=ev))

    return events
Example #2
0
def run_trigger(new_logs):
    """ Template trigger """
    events = []

    for ev in get_pause_events(new_logs):
        if ev.topic_0 == SIG_EVENT_YIELD_DISTRIBUTION:
            trustee, yield_amount, fee = decode_single(
                "(address,uint256,uint256)", decode_hex(ev.data))

            events.append(
                event_low("Fee Distributed to Trustee Account   πŸ•΄οΈ",
                          "**Yield**: {}\n"
                          "**Trustee**: {}\n"
                          "**Fee**: {}".format(
                              format_token_human('OUSD',
                                                 Decimal(yield_amount)),
                              trustee,
                              format_token_human('OUSD', Decimal(fee)),
                          ),
                          log_model=ev))

        elif ev.topic_0 == SIG_EVENT_TRUSTEE_ADDRESS_CHANGED:
            trustee = decode_single("(address)", decode_hex(ev.data))[0]

            events.append(
                event_low("Trustee Changed   πŸ•΄οΈβž‘οΈπŸ•΄οΈ",
                          "**New Trustee**: {}".format(trustee),
                          log_model=ev))

        elif ev.topic_0 == SIG_EVENT_TRUSTEE_FEE_CHANGED:
            bps = decode_single("(uint256)", decode_hex(ev.data))[0]

            events.append(
                event_low("Trustee Fee Changed   πŸ’²πŸ•΄οΈ",
                          "**New Fee**: {}bps".format(bps),
                          log_model=ev))

    return events
def run_trigger(new_logs):
    """ Template trigger """
    events = []

    for ev in get_events(new_logs):
        asset = decode_single('(address)', decode_hex(ev.topic_1))[0]
        ptoken, amount = decode_single('(address,uint256)',
                                       decode_hex(ev.data))

        asset_name = SYMBOL_FOR_CONTRACT.get(asset, asset)
        contract_name = CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address)

        if ev.topic_0 == SIG_EVENT_DEPOSIT:
            events.append(
                event_low("Deposit   🔼",
                          "{} {} was deposited to the {}\n\n".format(
                              format_token_human(asset_name, amount),
                              asset_name,
                              contract_name,
                          ),
                          log_model=ev))

        elif ev.topic_0 == SIG_EVENT_WITHDRAWAL:
            events.append(
                event_low("Withdrawal   🔽",
                          "{} {} was withdrawn from the {}\n\n".format(
                              format_token_human(asset_name, amount),
                              asset_name,
                              contract_name,
                          ),
                          log_model=ev))

        else:
            # Theoretically impossible
            raise Exception('Unexpected event')

    return events
def run_trigger(new_logs):
    """ Template trigger """
    events = []

    for ev in get_events(new_logs):

        if ev.topic_0 == SIG_EVENT_START_VOTE:
            # StartVote(
            #     uint256 indexed voteId,
            #     address indexed creator,
            #     string metadata,
            #     uint256 minBalance,
            #     uint256 minTime,
            #     uint256 totalSupply,
            #     uint256 creatorVotingPower
            # )
            vote_id = decode_single('(uint256)', decode_hex(ev.topic_1))[0]
            creator = decode_single('(address)', decode_hex(ev.topic_2))[0]
            (
                metadata_hash,
                min_balance,
                min_time,
                total_supply,
                creator_voting_power,
            ) = decode_single("(string,uint256,uint256,uint256,uint256)",
                              decode_hex(ev.data))

            metadata = fetch_ipfs_json(
                strip_terrible_ipfs_prefix(metadata_hash))
            """ 51% Voting contract is for contract deployments and 60% Voting
            contract is for parameter changes
            """
            vote_url = 'https://dao.curve.fi/vote/{}/{}'.format(
                'ownership' if ev.address == CURVE_ARAGON_51 else 'parameter',
                vote_id,
            )

            details = ("**Creator**: {} \n"
                       "**Creator Voting Power**: {} veCRV\n"
                       "**Minimum vote balance**: {} veCRV\n"
                       "**Current total supply**: {} veCRV\n"
                       "**Minimum time**: {}\n"
                       "**Metadata**: {}\n\n"
                       "{}").format(
                           creator,
                           format_token_human('veCRV', creator_voting_power),
                           format_token_human('veCRV', min_balance),
                           format_token_human('veCRV', total_supply),
                           format_timedelta(timedelta(seconds=min_time)),
                           metadata.get('text', 'NO METADATA TEXT FOUND.'),
                           vote_url,
                       )

            events.append(
                event_high("{} - Vote Created ({})   πŸ—³οΈ πŸ†•".format(
                    CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address),
                    vote_id,
                ),
                           details,
                           log_model=ev))

        elif ev.topic_0 == SIG_EVENT_EXECUTE_VOTE:
            # ExecuteVote(uint256 indexed voteId)
            vote_id = decode_single('(uint256)', decode_hex(ev.topic_1))[0]

            events.append(
                event_high(
                    "{} - Vote Executed ({})   πŸ—³οΈ βš™οΈ".format(
                        CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address),
                        vote_id,
                    ),
                    "Curve Aragon DAO vote #{} on the {} voting app has been "
                    "executed".format(
                        vote_id,
                        CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address),
                    ),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_SCRIPT_RESULT:
            # ScriptResult(
            #     address indexed executor,
            #     bytes script,
            #     bytes input,
            #     bytes returnData
            # )
            executor = decode_single('(address)', decode_hex(ev.topic_1))[0]
            # script, input_data, return_data = decode_single(
            #     "(bytes,bytes,bytes)",
            #     decode_hex(ev.data),
            # )
            """ TODO: Decode this further?  Right now I don't think it's worth
            the effort, though we're putting a bit of trust into the prop that
            it's nothing nefarious.  Might be worth coming back to this.  Only
            problem is that it appears to be EVM-level instructions...

            Ref: https://hack.aragon.org/docs/evmscript_EVMScriptRunner
            Ref: https://github.com/aragon/aragonOS/blob/f3ae59b00f73984e562df00129c925339cd069ff/contracts/evmscript/EVMScriptRunner.sol#L34-L100
            """
            # print('script', script)
            # print('input_data:', input_data)
            # print('return_data:', return_data)

            events.append(
                event_normal("{} - Execution Result   πŸ—³οΈ πŸͺ£".format(
                    CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address)),
                             "Executed by: {}".format(executor),
                             log_model=ev))

    return events
Example #5
0
def run_trigger(new_logs):
    """ Template trigger """
    events = []

    for ev in get_events(new_logs):

        if ev.topic_0 == SIG_EVENT_CHANGE_SUPPORT_REQUIRED:
            # ChangeSupportRequired(uint64 supportRequiredPct)
            support_required = decode_single('(uint64)',
                                             decode_hex(ev.data))[0]

            events.append(
                event_high(
                    "{} - Support Required Changed   🎚️".format(
                        CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address)),
                    "{}% support is now required for a vote pass. \n\n"
                    "NOTE: This is unexpected due to two contracts for different "
                    "voting levels.".format(Decimal(support_required) / E_18),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_CHANGE_MIN_QUORUM:
            # ChangeMinQuorum(uint64 minAcceptQuorumPct)
            min_quorum = decode_single('(uint64)', decode_hex(ev.data))[0]

            events.append(
                event_normal(
                    "{} - Support Minimum Quorum   🎚️".format(
                        CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address)),
                    "{}% quorum (yeas out of total supply) is now required for a vote."
                    .format(Decimal(min_quorum) / E_18),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_MIN_BALANCE_SET:
            # MinimumBalanceSet(uint256 minBalance)
            min_balance = decode_single('(uint256)', decode_hex(ev.data))[0]

            events.append(
                event_normal(
                    "{} - Minimum Balance   🎚️".format(
                        CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address)),
                    "Minimum balance of {} is now required to create a governance "
                    "vote.".format(format_token_human('veCRV', min_balance)),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_MIN_TIME_SET:
            # MinimumTimeSet(uint256 minTime)
            min_time = decode_single('(uint256)', decode_hex(ev.data))[0]

            events.append(
                event_normal(
                    "{} - Minimum Time   πŸ•“".format(
                        CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address)),
                    "Governance vote creation rate limit has been changed to "
                    "{}.".format(format_timedelta(
                        timedelta(seconds=min_time))),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_SET_APP:
            # SetApp(bytes32 indexed namespace, bytes32 indexed appId, address app)
            namespace = decode_single('(bytes32)', decode_hex(ev.topic_1))[0]
            app_id = decode_single('(bytes32)', decode_hex(ev.topic_1))[0]
            app_address = decode_single('(address)', decode_hex(ev.data))[0]

            events.append(
                event_high(
                    "{} - New App Set   πŸ“›".format(
                        CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address)),
                    "A new Aragon app has been set for the Curve Voting Fork. "
                    "This is expected to only happen on app creation.\n\n"
                    "Namespace: {}\n"
                    "App ID: {}\n"
                    "App Address: {}\n".format(
                        namespace,
                        app_id,
                        app_address,
                    ),
                    log_model=ev))

    return events
Example #6
0
def run_trigger(new_logs):
    """ Compound Timelock changes """
    events = []

    for ev in get_events(new_logs):
        if ev.topic_0 == SIG_EVENT_AAVE_PROPOSAL_CREATED:
            """
            event ProposalCreated(
                uint256 indexed proposalId,
                bytes32 indexed ipfsHash,
                bytes32 indexed proposalType,
                uint256 propositionPowerOfCreator,
                uint256 threshold,
                uint256 maxMovesToVotingAllowed,
                uint256 votingBlocksDuration,
                uint256 validatingBlocksDuration,
                address proposalExecutor
            )
            """
            proposal_id = decode_single("(uint256)", decode_hex(ev.topic_1))[0]
            ipfs_hash = decode_single("(bytes32)", decode_hex(ev.topic_2))[0]
            # proposal_type = decode_single(
            #     "(bytes32)",
            #     decode_hex(ev.topic_3)
            # )[0]
            (
                proposition_power_of_creator,
                threshold,
                max_moves_to_voting_allowed,
                voting_blocks_duration,
                validating_blocks_duration,
                proposal_executor,
            ) = decode_single(
                "(uint256,uint256,uint256,uint256,uint256,address)",
                decode_hex(ev.data))

            b58_ipfs_data = decode_ipfs_hash(encode_hex(ipfs_hash))
            ipfs_data = fetch_ipfs_json(b58_ipfs_data)
            prop_headers = parse_prop_headers(ipfs_data)
            aip = prop_headers.get('aip')

            if aip:
                aip_link = 'https://aave.github.io/aip/AIP-{}'.format(aip)
            else:
                aip_link = '[UNKNOWN AIP]'

            events.append(
                event_high(
                    "Aave (v1) Governance Proposal Created (ID: {})   πŸ—³οΈ πŸ†•".
                    format(proposal_id),
                    "A new proposal (ID: {}) has been submitted for Aave"
                    "\n\n"
                    "**Title**: {}\n"
                    "**Description**: {}\n\n"
                    "**Threshold**: {} AAVE\n"
                    "**Voting Duration** {} blocks (approx {} days)\n"
                    "**Validating Duration** {} blocks (approx {} days)\n"
                    "**Executor**: {}\n"
                    "**IPFS Hash**: {}\n"
                    "{}".format(
                        proposal_id,
                        ipfs_data.get('title'),
                        ipfs_data.get('shortDescription'),
                        format_token_human('AAVE', Decimal(threshold)),
                        voting_blocks_duration,
                        round(
                            Decimal(voting_blocks_duration) / BLOCKS_PER_DAY,
                            2),
                        validating_blocks_duration,
                        round(
                            Decimal(validating_blocks_duration) /
                            BLOCKS_PER_DAY, 2),
                        proposal_executor,
                        decode_ipfs_hash(encode_hex(ipfs_hash)),
                        aip_link,
                    ),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_STATUS_CHANGE_TO_VALIDATING:
            # StatusChangeToValidating(uint256 indexed proposalId)
            proposal_id = decode_single("(uint256)", decode_hex(ev.topic_1))[0]

            events.append(
                event_high(
                    "Aave proposal moved to validating   πŸ—³οΈ πŸ”",
                    "Aave proposal #{} is now in validating stage awaiting "
                    "challenges".format(proposal_id),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_STATUS_CHANGE_TO_VOTING:
            """
            StatusChangeToVoting(
                uint256 indexed proposalId,
                uint256 movesToVoting
            )
            """
            proposal_id = decode_single("(uint256)", decode_hex(ev.topic_1))[0]

            events.append(
                event_high("Aave proposal moved to voting   πŸ—³οΈ πŸ“₯",
                           "Aave proposal #{} is now in voting stage".format(
                               proposal_id),
                           log_model=ev))

        elif ev.topic_0 == SIG_EVENT_STATUS_CHANGE_TO_EXECUTED:
            """ StatusChangeToExecuted(uint256 indexed proposalId) """
            proposal_id = decode_single("(uint256)", decode_hex(ev.topic_1))[0]

            events.append(
                event_normal("Aave proposal has been resolved   πŸ—³οΈ βš™οΈ",
                             "Aave proposal #{} has now been resolved".format(
                                 proposal_id),
                             log_model=ev))

        elif ev.topic_0 == SIG_EVENT_WINS_YES:
            """
            YesWins(
                uint256 indexed proposalId,
                uint256 abstainVotingPower,
                uint256 yesVotingPower,
                uint256 noVotingPower
            )
            """
            proposal_id = decode_single("(uint256)", decode_hex(ev.topic_1))[0]

            events.append(
                event_high(
                    "Aave proposal has been passed   πŸ—³οΈ βœ…",
                    "Aave proposal #{} has been passed".format(proposal_id),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_WINS_NO:
            """
            NoWins(
                uint256 indexed proposalId,
                uint256 abstainVotingPower,
                uint256 yesVotingPower,
                uint256 noVotingPower
            )
            """
            proposal_id = decode_single("(uint256)", decode_hex(ev.topic_1))[0]

            events.append(
                event_high(
                    "Aave proposal has failed   πŸ—³οΈ ❎",
                    "Aave proposal #{} has been rejected".format(proposal_id),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_WINS_ABSTAIN:
            """
            AbstainWins(
                uint256 indexed proposalId,
                uint256 abstainVotingPower,
                uint256 yesVotingPower,
                uint256 noVotingPower
            )
            """
            proposal_id = decode_single("(uint256)", decode_hex(ev.topic_1))[0]

            events.append(
                event_high(
                    "Aave proposal has failed by abstention   πŸ—³οΈ 〰️",
                    "Aave proposal #{} has been rejected by abstention".format(
                        proposal_id),
                    log_model=ev))

    return events