def run_trigger(new_logs):
    """ Look for mints and redeems """
    events = []

    for ev in get_strategy_events(new_logs):
        title = ''
        description = ''

        if ev.topic_0 == SIG_EVENT_DEFAULT_STRATEGY:
            title = 'Asset Default Strategy Set   ♟️'
            asset, strat_addr = decode_single('(address,address)',
                                              decode_hex(ev.data))
            description = (
                'New default strategy for {} has been set to {}').format(
                    SYMBOL_FOR_CONTRACT.get(asset, asset),
                    strat_addr,
                )

        elif ev.topic_0 == SIG_EVENT_STRATEGY_APPROVED:
            title = 'Strategy Added To Vault    🏦♟️'
            strat_addr = decode_single('(address)', decode_hex(ev.data))
            description = 'New strategy {} has been added to the vault'.format(
                strat_addr, )

        elif ev.topic_0 == SIG_EVENT_STRATEGY_ADDED:
            title = 'Strategy Added   ♘'
            strat_addr = decode_single('(address)', decode_hex(ev.data))
            description = 'https://etherscan.io/address/{}'.format(strat_addr)

        elif ev.topic_0 == SIG_EVENT_STRATEGY_REMOVED:
            title = 'Strategy Removed   ♞'
            strat_addr = decode_single('(address)', decode_hex(ev.data))
            description = 'https://etherscan.io/address/{}'.format(strat_addr)

        elif ev.topic_0 == SIG_EVENT_WEIGHTS_UPDATED:
            title = 'Strategy Weights Updated   ⚖️'
            addresses, weights = decode_single('(address[],uint256[])',
                                               decode_hex(ev.data))
            for i, address in enumerate(addresses):
                description += '\n{} {}'.format(address, weights[i])

        events.append(event_high(title, description, log_model=ev))

    return events
Пример #2
0
def run_trigger(new_logs):
    """ Trigger events on Compound Timelock transaction events """
    events = []

    for ev in get_events(new_logs):
        summary = "ERROR"
        action = "ERROR"

        if ev.topic_0 == SIG_EVENT_QUEUE_TRANSACTION:
            summary = "Compound Timelock transaction queued   ⏲️ 📥"
            action = "queued"
        elif ev.topic_0 == SIG_EVENT_CANCEL_TRANSACTION:
            summary = "Compound Timelock transaction canceled   ⏲️ ❌"
            action = "canceled"
        elif ev.topic_0 == SIG_EVENT_EXECUTE_TRANSACTION:
            summary = "Compound Timelock transaction executed   ⏲️ 🏃‍♀️"
            action = "executed"

        # They all have the same args so most of thise can be reused
        # tx_hash = decode_single("(bytes32)", decode_hex(ev.topic_1))[0]
        target = decode_single("(address)", decode_hex(ev.topic_2))[0]
        value, signature, data, eta_stamp = decode_single(
            "(uint256,string,bytes,uint256)", decode_hex(ev.data))

        eta = datetime.utcfromtimestamp(eta_stamp)
        call = decode_call(signature, data)

        events.append(
            event_high(summary,
                       "Compound Timelock transaction has been {}\n\n"
                       "**Target**: {}\n"
                       "**ETA**: {} UTC\n"
                       "**Call**: {}".format(
                           action,
                           CONTRACT_ADDR_TO_NAME.get(target, target),
                           eta,
                           call,
                       ),
                       log_model=ev))

    return events
def run_trigger(new_logs):
    """ Compound Timelock changes """
    events = []

    for ev in get_events(new_logs):

        if ev.topic_0 == SIG_EVENT_PROPOSAL_CREATED:
            # ProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, uint startBlock, uint endBlock, string description)
            (
                proposal_id, proposer, targets, values, signatures, calldatas,
                start_block, end_block, description
            ) = decode_single(
                "(uint256,address,address[],uint256[],string[],bytes[],uint256,uint256,string)",
                decode_hex(ev.data))

            details = create_prop_details(
                proposal_id,
                description,
                proposer,
                targets,
                signatures,
                calldatas,
                start_block,
                end_block,
            )

            # If the message is too long, truncate description only
            if len(details) > DISCORD_EMBED_DESCRIPTION_LIMIT:
                diff = len(details) - DISCORD_EMBED_DESCRIPTION_LIMIT
                details = create_prop_details(
                    proposal_id,
                    truncate_elipsis(description,
                                     max_length=len(description) - diff),
                    proposer,
                    targets,
                    signatures,
                    calldatas,
                    start_block,
                    end_block,
                )

            events.append(
                event_high(
                    "Compound Governor Proposal Created ({})   🗳️ 🆕".format(
                        proposal_id),
                    details,
                    log_model=ev))

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

            events.append(
                event_high(
                    "Compound GovernorAlpha proposed cancelled   🗳️ ❌",
                    "Compound GovernorAlpha proposal #{} has been canceled".
                    format(proposal_id),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_PROPOSAL_QUEUED:
            proposal_id, eta_stamp = decode_single("(uint256,uint256)",
                                                   decode_hex(ev.data))

            eta = datetime.utcfromtimestamp(eta_stamp)

            events.append(
                event_high(
                    "Compound GovernorAlpha proposed queued   🗳️ 📥",
                    "Compound GovernorAlpha proposal #{} has been queued "
                    "for {} UTC".format(
                        proposal_id,
                        eta,
                    ),
                    log_model=ev))

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

            events.append(
                event_high(
                    "Compound GovernorAlpha proposed executed   🗳️ ⚙️",
                    "Compound GovernorAlpha proposal #{} has been executed".
                    format(proposal_id, ),
                    log_model=ev))

        # This is a ton of noise that's probably irrelevant to us.  Will leave
        # it here in case we change our minds.
        #
        # elif ev.topic_0 == SIG_EVENT_VOTE_CAST:
        #     # VoteCast(address voter, uint proposalId, bool support, uint votes)
        #     (
        #         voter,
        #         proposal_id,
        #         support,
        #         votes
        #     ) = decode_single(
        #         "(address,uint256,bool,uint256)",
        #         decode_hex(ev.data)
        #     )

        #     events.append(event_low(
        #         "Compound GovernorAlpha vote   🗳️",
        #         "{} has voted {} of proposal #{}".format(
        #             voter,
        #             "in support ✔️" if support else "in opposition ❌",
        #             proposal_id,
        #         )
        #     ))

    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
Пример #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
Пример #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