Code Monkey home page Code Monkey logo

ape-safe's Introduction

Quick Start

Account plugin for the Safe Multisig wallet (previously known as Gnosis Safe).

Dependencies

Installation

via ape

You can install using the ape built-in plugin manager:

$ ape plugins install safe

via pip

You can install the latest release via pip:

$ pip install ape-safe

via setuptools

You can clone the repository and use setuptools for the most up-to-date version:

$ git clone https://github.com/ApeWorX/ape-safe.git
$ cd ape-safe
$ python3 setup.py install

Quick Usage

To use the plugin, first use the CLI extension to add a safe you created:

ape safe add --network ethereum:mainnet "my-safe.eth" my-safe

If you made a mistake or just need to remove the safe, use the remove command:

ape safe remove my-safe --yes

NOTE --yes is a way to skip the prompt.

If you only add one safe, you will not have to specify which safe to use other commands. Otherwise, for most pending commands, you specify the safe to use (by alias) via the --safe option.

Additionally, you can configure a safe to use as the default in your ape-config.yaml file:

safe:
  default_safe: my-safe

NOTE: Also, to avoid always needing to specify --network, you can set a default ecosystem, network, and provider in your config file. The rest of the guide with not specify --network on each command but assume the correct one is set in the config file. Here is an example:

default_ecosystem: optimism

ethereum:
  default_network: sepolia
  sepolia:
    default_provider: infura

Once you have a safe, you can view pending transactions:

ape safe pending list

It should show transactions like this:

Transaction 8 rejection (1/2) safe_tx_hash=0x09ab9a229fc60da66ec0fa8fa886ab7c95902fdf5df5a5009ba06010fbb9a9a7
Transaction 8 transfer  (1/2) safe_tx_hash=0xed43d80255bcd5ffacb755e8f51bee825913373705d6baea006419d2a33a0a5b

NOTE: Use the --verbose flag to see more information about each transaction.

ape safe pending list --verbose

There are several operations you can do on a pending transaction. One of them is "approve" which adds your local signers' signatures to the transaction.

ape safe pending approve 0x09ab9a229fc60da66ec0fa8fa886ab7c95902fdf5df5a5009ba06010fbb9a9a7

NOTE: Here we are using the transaction hash 0x09ab9a229fc60da66ec0fa8fa886ab7c95902fdf5df5a5009ba06010fbb9a9a7 to specify the transaction because there are more than one. However, you can also use the nonce if there is only a single transaction.

If you want to both execute and approve at the same time, you can use the --execute option on approve and specify a sender:

ape safe pending approve 2 --execute my_account

Else, you can use the execute command directly:

ape safe pending execute 2

NOTE: execute requires a full signed transaction ready to be submitted on-chain.

The last main operation is reject. Rejecting a transaction replaces that transaction with a zero-value transfer from the safe to itself.

ape safe pending reject 2

Multisend

The following example shows how to use multisend:

from ape_safe import multisend
from ape import accounts
from ape_tokens import tokens

safe = accounts.load("my-safe")

# Load some contracts (here using ape-tokens)
dai = tokens["DAI"]
vault = tokens["yvDAI"]
amount = dai.balanceOf(safe)  # How much we want to deposit

# Create a multisend transaction (a transaction that executes multiple calls)
txn = multisend.MultiSend()
txn.add(dai.approve, vault, amount)
txn.add(vault.deposit, amount)

# Fetch signatures from any local signers, and broadcast if confirmations are met
# Note that in case the user intends to only stage a transaction, then `submit=False` argument can also be added
# It is normal that when a user only intend to stage a transaction, an error is thrown
# this can be ignored by including the necessary try-catch (from ape.exceptions import SignatureError)
# Note that transaction is automatically prompted for execution if enough signers are available in local
txn(sender=safe,gas=0)

Development

Please see the contributing guide to learn more how to contribute to this project. Comments, questions, criticisms and pull requests are welcomed.

Acknowledgements

This package was inspired by the original ape-safe by banteg. For versions prior to v0.6.0, the original package should be referenced.

ape-safe's People

Contributors

antazoey avatar banteg avatar dtdang avatar fubuloubu avatar notpeopling2day avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ape-safe's Issues

Error when attempting to install ape-safe via pip install and ape plugin install [APE-1367]

Environment information

  • ape and plugin versions:
(venv) user@Users-Laptop safe % ape --version
0.6.15
(venv) user@Users-Laptop safe % ape plugins list
No plugins installed. Use '--all' to see available plugins.
  • Python Version: 3.10.12
  • OS: OSX

What went wrong?

Error when attempting to install ape-safe via pip install and ape plugin install

(venv) user@Users-Laptop safe % ape plugins install safe
INFO: Installing safe...
  error: subprocess-exited-with-error
  
  × Getting requirements to build wheel did not run successfully.
  │ exit code: 1
  ╰─> [86 lines of output]
      
      Error compiling Cython file:
      ------------------------------------------------------------
      ...
          cdef readonly object func
          cdef readonly tuple args
          cdef readonly dict keywords
          cdef public object __doc__
          cdef public object __name__
          cdef public object __module__
                             ^
      ------------------------------------------------------------
      
      cytoolz/functoolz.pxd:18:23: '__module__' redeclared
      
      Error compiling Cython file:
      ------------------------------------------------------------
      ...
          cdef readonly object func
          cdef readonly tuple args
          cdef readonly dict keywords
          cdef public object __doc__
          cdef public object __name__
          cdef public object __module__
               ^
      ------------------------------------------------------------
      
      cytoolz/functoolz.pxd:18:9: Compiler crash in AnalyseDeclarationsTransform
      
      File 'ModuleNode.py', line 203, in analyse_declarations: ModuleNode(functoolz.pxd:1:0,
          full_module_name = 'cytoolz.functoolz',
          is_pxd = True)
      File 'Nodes.py', line 393, in analyse_declarations: StatListNode(functoolz.pxd:1:0)
      File 'Nodes.py', line 5497, in analyse_declarations: CClassDefNode(functoolz.pxd:10:5,
          as_name = 'curry',
          class_name = 'curry',
          in_pxd = True,
          module_name = '',
          punycode_class_name = 'curry',
          visibility = 'private')
      File 'Nodes.py', line 393, in analyse_declarations: StatListNode(functoolz.pxd:11:4)
      File 'Nodes.py', line 1528, in analyse_declarations: CVarDefNode(functoolz.pxd:18:9,
          in_pxd = True,
          modifiers = [...]/0,
          visibility = 'public')
      
      Compiler crash traceback from this point on:
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/Cython/Compiler/Nodes.py", line 1528, in analyse_declarations
          self.entry = dest_scope.declare_var(
                       ^^^^^^^^^^^^^^^^^^^^^^^
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/Cython/Compiler/Symtab.py", line 2389, in declare_var
          entry = self.declare(name, cname, type, pos, visibility)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/Cython/Compiler/Symtab.py", line 550, in declare
          entries[name].already_declared_here()
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/Cython/Compiler/Symtab.py", line 262, in already_declared_here
          error(self.pos, "Previous declaration is here")
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/Cython/Compiler/Errors.py", line 178, in error
          raise InternalError(message)
      InternalError: Internal compiler error: Previous declaration is here
      [1/5] Cythonizing cytoolz/dicttoolz.pyx
      [2/5] Cythonizing cytoolz/functoolz.pyx
      Traceback (most recent call last):
        File "/Users/user/.local/pipx/shared/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
          main()
        File "/Users/user/.local/pipx/shared/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/Users/user/.local/pipx/shared/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 118, in get_requires_for_build_wheel
          return hook(config_settings)
                 ^^^^^^^^^^^^^^^^^^^^^
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 355, in get_requires_for_build_wheel
          return self._get_build_requires(config_settings, requirements=['wheel'])
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 325, in _get_build_requires
          self.run_setup()
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 507, in run_setup
          super(_BuildMetaLegacyBackend, self).run_setup(setup_script=setup_script)
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 341, in run_setup
          exec(code, locals())
        File "<string>", line 85, in <module>
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/Cython/Build/Dependencies.py", line 1134, in cythonize
          cythonize_one(*args)
        File "/private/var/folders/3_/z8rn91w566l816hsprr2k4w80000gn/T/pip-build-env-e05_0hgb/overlay/lib/python3.11/site-packages/Cython/Build/Dependencies.py", line 1301, in cythonize_one
          raise CompileError(None, pyx_file)
      Cython.Compiler.Errors.CompileError: cytoolz/functoolz.pyx
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

ERROR: Failed to install plugin 'safe.

How can it be fixed?

Fill this in if you have ideas on how the bug could be fixed.

Publish docs for current usage

Overview

The current docs are copies of the old brownie safe package

Specification

Update the docs using modern examples for all of the examples in the legacy docs

Dependencies

Also publish docs for this using our docs template

Cache signatures

Overview

Not sure if this a good idea, but sometimes when you are having to play with a transaction to get it working, you might need to submit it multiple times with different gas values (such as if the gas price keeps rising or something), it would be great in this scenario not to have to call sign_transaction multiple times with the safe, since the request will be the same.

One potential solution is to "cache" the signatures for a given SafeTx hash, since those signatures are likely to continue being valid. You might also want to submit it to the Safe API if it fails the first time, so you can come back and execute it later.

Specification

No UX changes, it just caches by SafeTxID under the hood

Dependencies

n/a

Arbitrum - Can't Add Safe

Environment information

  • ape and plugin versions:
$ ape --version
0.7.7

$ ape plugins list
Installed Plugins
  alchemy      0.7.1
  arbitrum     0.7.1
  etherscan    0.7.0
  foundry      0.7.1
  optimism     0.7.2
  safe         0.7.0b1
  solidity     0.7.1

  • Python Version: 3.9.0
  • OS: osx/linux/win linux

What went wrong?

Running the below to add a safe

(gnosis_test_ape) thesis@ks:~/repos/gnosis_test_ape$ ape safe add 0xBFd8c1f83C5389a64166F01fea0D56d982F627Ac "arbitrum-test" --network arbitrum:mainnet:alchemy

returns an error

ERROR: (ApeAttributeError) 'GnosisSafeProxy' has no attribute 'VERSION'.

Please include information like:

  • what command you ran done
  • the code that caused the failure (see this link for help with formatting code)
  • full output of the error you received done

How can it be fixed?

Fill this in if you have ideas on how the bug could be fixed.

auto use safe when there is only one [APE-1398]

Overview

My goal is to avoid having to unnecessarily declare the safe when I only am using 1 safe.

You get this error when you don't tell ape-safe to use the one and only safe:

Error: Missing argument '{ape-safe-test}'. Choose from:
        ape-safe-test

Specification

ape safe pending --network ethereum:goerli

uses the safe rather than forcing me to do:

ape safe pending --network ethereum:goerli <SAFE-NAME>

Dependencies

Include links to any open issues that must be resolved before this feature can be implemented.

Add delegate support [APE-1293]

note: a delegate can submit a tx to SafeAPI even if it has zero signatures.

things related to "delegate" in Safe's tx svc api here: https://github.com/safe-global/safe-eth-py/blob/master/gnosis/safe/api/transaction_service_api.py

any safe signer can manage delegates by submitting a special message to the api.

Also, if submitter= is a delegate account or alias it should bypass this logic and submit it. I check elsewhere if they're a signer only for signature aggregation.

Originally posted by @banteg in #11 (comment)

Gas estimation issues w/ MultiSend [APE-1294]

@banteg:

still encountering problems when trying to submit a multisend tx. they are mostly coming from gas estimation:

  • prepare_transaction tries to estimate gas from a safe address
  • it fails when the safe has no ether to cover the gas costs, but in reality safe itself never pays for gas
  • it fails because it tries to estimate a call to the multisend contract, while it only supports delegatecall

we need to somehow override the tx handler or find a way to pass additional metadata to skip some checks

Originally posted by @banteg in #11 (comment)

simplify multisend contract address detection

DEFAULT_ADDRESS = "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761"
DEPLOYMENT_ADDRESS = {
10: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
25: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
28: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
61: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
63: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
69: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
82: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
83: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
106: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
111: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
288: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
322: "0x6367360366E4c898488091ac315834B779d8f561",
338: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
420: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
588: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
595: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
599: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
686: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
787: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
1001: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
1088: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
1294: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
7700: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
8217: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
10000: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
10001: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
42220: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
43114: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
54211: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
71401: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
71402: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
11155111: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
1666600000: "0x998739BFdAAdde7C933B942a68053933098f9EDa",
1666700000: "0x998739BFdAAdde7C933B942a68053933098f9EDa",

there are only two addresses ever. any address will do, and we can just use the first address that has code. see how it's done here:

https://github.com/safe-global/safe-eth-py/blob/ae5ebe0dee0556157bcb7c2370c3d0732e1f3e59/gnosis/safe/multi_send.py#L171-L178

another important thing is we should switch to multisend call only version because it prevents the user from accidentally corrupting safe storage with a delegatecall.

Ape cannot compute gas cost estimation if Safe has zero balance

Environment information

  • ape and plugin versions:
$ ape --version
0.7.9

$ ape plugins list
Installed Plugins
  alchemy      0.7.1
  arbitrum     0.7.2
  etherscan    0.7.1
  foundry      0.7.3
  infura       0.7.1
  ledger       0.7.0
  optimism     0.7.2
  safe         0.7.0b1
  tokens       0.7.1
  • Python Version: 3.11.7
  • OS: linux

What went wrong?

I am trying to execute a transaction directly on a public network using the Safe plugin (but aiming to publish to the Safe API only)

  File "site-packages/ape_ethereum/provider.py", line 249, in estimate_gas_cost
    return self.web3.eth.estimate_gas(txn_params, block_identifier=block_id)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/web3/eth/eth.py", line 312, in estimate_gas
    return self._estimate_gas(transaction, block_identifier)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/web3/module.py", line 75, in caller
    result = w3.manager.request_blocking(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/web3/manager.py", line 326, in request_blocking
    return self.formatted_response(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/web3/manager.py", line 289, in formatted_response
    raise ValueError(error)
ValueError: {'code': -32000, 'message': 'insufficient funds for transfer'}

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "script.py", line 38, in foo
    contract.methodName(sender=safe, submit_transaction=False)
  File "site-packages/ape/contracts/base.py", line 356, in __call__
    return contract_transaction(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/ape/contracts/base.py", line 290, in __call__
    return kwargs["sender"].call(txn, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "python3.11/contextlib.py", line 81, in inner
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "site-packages/ape_safe/accounts.py", line 531, in call
    return super().call(txn, **call_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/ape/api/accounts.py", line 125, in call
    txn = self.prepare_transaction(txn)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/ape_safe/accounts.py", line 462, in prepare_transaction
    return self.provider.prepare_transaction(txn)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/ape_ethereum/provider.py", line 861, in prepare_transaction
    gas = self.estimate_gas_cost(txn)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/ape_ethereum/provider.py", line 259, in estimate_gas_cost
    raise TransactionError(
ape.exceptions.TransactionError: Gas estimation failed: 'insufficient funds for transfer'. This transaction will likely revert. If you wish to broadcast, you must set the gas limit manually.

How can it be fixed?

I believe the root cause to be that the Safe I am using to execute has zero balance, leading web3py to fail when calling eth_estimateGas. Some effort to bypass this behavior or override the balance of the contract could help assist in properly determining the gas cost it would take.

`operation` is not propagated when serializing to `TransactionAPI`

operation denotes a call type (0=call, 1=delegatecall). the transaction would fail if we encode the wrong operation types. multisend specifically requires to be only called as a delegatecall.

users can currently work around this by passing a kwarg like txn(sender=safe, operation=1), but this is not very convenient and it should be fixed either in the library of ape api to allow passing it over.

txn_kwargs["operation"] = 1

support working with eip-1271 messages

Overview

safe transaction service has recently added support for aggregating signatures for off-chain messages.

the flow for them is similar to transactions, except they never get executed and instead are passed to other contracts, that check isValidSignature. for example, this enables sending cowswap orders in a completely off-chain manner.

we could support them via AccountAPI.sign_message

Specification

see here for an example/reference:
https://gist.github.com/banteg/68ad51b133d447aa4a165bea0c7b91a1

see here for the client api:
https://safe-transaction-mainnet.safe.global/

Dependencies

depends on ApeWorX/ape#1508

Add smarter network detection to use as default network

I wish there was a way for network detection to be smarter in the safe. I purposely named my safes the same alias as the one generated in the UI, like laughing-sepolia-safe... It'd be cool maybe if could detect sepolia somehow and my default sepolia provider. It feel redundant to have to specify the network. Maybe the network can be included in the safe account data.

Originally posted by @antazoey in #41 (comment)

Refactor to multi-chain service

Overview

Safe has a multi-chain proxy service that works across all of their backends, it would be easier to support this via client then to add (and test) one-per-network

Specification

https://safe-client.safe.global/api

Dependencies

Include links to any open issues that must be resolved before this feature can be implemented.

`ape safe pending approve` fails if transaction is fully confirmed before executing

Environment information

  • ape and plugin versions:
$ ape --version
0.7.9

$ ape plugins list
Installed Plugins
  alchemy      0.7.1
  arbitrum     0.7.2
  etherscan    0.7.1
  foundry      0.7.3
  infura       0.7.1
  ledger       0.7.0
  optimism     0.7.2
  safe         0.7.0b1
  tokens       0.7.1
  • Python Version: 3.11.7
  • OS: linux

What went wrong?

$ ape safe pending approve X --network ethereum:mainnet --safe mine
SignableMessage(version="E", header="thereum Signed Message:
32", body="0xc878....cf40")

Sign:  [y/N]: y
Enter passphrase to unlock 'hot' []: 
Leave 'hot' unlocked? [y/N]: y
SUCCESS: Signatures added to transaction 'X' using accounts '0x....'.
Submit transaction 'X' [y/N]: y
0. cold
1. hot
Or 'TEST::account_idx', where `account_idx` is in [0..{len_test_accounts}]

Select a submitter: dev
Traceback (most recent call last):
  File "bin/ape", line 8, in <module>
    sys.exit(cli())
             ^^^^^
  File "site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "ape/_cli.py", line 79, in invoke
    return super().invoke(ctx)
           ^^^^^^^^^^^^^^^^^^^
  File "site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "ape/cli/commands.py", line 96, in invoke
    return self._invoke(ctx, provider=provider)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "ape/cli/commands.py", line 133, in _invoke
    return ctx.invoke(self.callback or (lambda: None), **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/click/decorators.py", line 92, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "site-packages/ape_safe/_cli/pending.py", line 219, in approve
    txn.confirmations = {**txn.confirmations, **signatures_added}
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'list' object is not a mapping

How can it be fixed?

Fill this in if you have ideas on how the bug could be fixed.

inject abi from fallback handler to safe

a safe actually contains a bit more functionality like eip-1271 signature support behind fallback handler. it would be useful to extend the contract type with abis from it.

the fallback handler can be read from slot keccak("fallback_manager.handler.address") of a safe.

Add full plugin documentation and integrate to Ape docs hub [APE-1295]

Overview

This is a very complex plugin, so it's worth adding additional color to README on usage at a high level, maybe 1-2 user guides for using it in different scenarios (perhaps for Personal use and for Collective use), another user guide on the CLI extension, and autodocs for the various classes (similar to ape)

Api Update

Environment information

  • ape and plugin versions:
$ ape --version
0.7.23

$ ape plugins list
Installed Plugins
  alchemy      0.7.3
  etherscan    0.7.4
  foundry      0.7.5
  optimism     0.7.3
  safe         0.7.0b2
  solidity     0.7.3
  • Python Version: 3.12
    b- OS: osx/linux/win linux

What went wrong?

The safe api changed for fetching transactions, i believe v1/safes/{address}/transactions/ no longer works and is now
https://safe-transaction-optimism.safe.global/
/v1/safes/{address}/all-transactions/

url = f"safes/{self.address}/transactions"

Please include information like:

  • what command you ran
txn            = multisend.MultiSend()
txn(sender=self.safe,gas=0,submit_transaction=False,nonce=nonce)

Trying to push

  • the code that caused the failure (see this link for help with formatting code)
  • full output of the error you received
Traceback (most recent call last):
  File "/home/thesis/repos/gnosis_perp_ape/main.py", line 58, in <module>
    self.setup_gnosis_perp_parameter_change(args.p)
  File "/home/thesis/repos/gnosis_perp_ape/utils/controller.py", line 75, in setup_gnosis_perp_parameter_change
    self.post_gnosis_transaction(contractName='perp_settings',functionName=functionName,args=stagedParams)    
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thesis/repos/gnosis_perp_ape/utils/gnosis_safe.py", line 24, in wrapper
    return func(self,*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thesis/repos/gnosis_perp_ape/utils/gnosis_safe.py", line 64, in post_gnosis_transaction
    nonce          = self.get_next_safe_nonce()
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thesis/repos/gnosis_perp_ape/utils/gnosis_safe.py", line 24, in wrapper
    return func(self,*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thesis/repos/gnosis_perp_ape/utils/gnosis_safe.py", line 60, in get_next_safe_nonce
    return self.safe.new_nonce
           ^^^^^^^^^^^^^^^^^^^
  File "/home/thesis/miniconda3/envs/gnosis_perp_ape/lib/python3.12/site-packages/ape_safe/accounts.py", line 322, in new_nonce
    if latest_tx := next(self.client.get_transactions(confirmed=False), None):
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thesis/miniconda3/envs/gnosis_perp_ape/lib/python3.12/site-packages/ape_safe/client/base.py", line 81, in get_transactions
    for txn in self._all_transactions():
  File "/home/thesis/miniconda3/envs/gnosis_perp_ape/lib/python3.12/site-packages/ape_safe/client/__init__.py", line 86, in _all_transactions
    response = self._get(url)
               ^^^^^^^^^^^^^^
  File "/home/thesis/miniconda3/envs/gnosis_perp_ape/lib/python3.12/site-packages/ape_safe/client/base.py", line 128, in _get
    return self._request("GET", url)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/thesis/miniconda3/envs/gnosis_perp_ape/lib/python3.12/site-packages/ape_safe/client/base.py", line 153, in _request
    raise ClientResponseError(api_url, response)
ape_safe.exceptions.ClientResponseError: Exception when calling 'https://safe-transaction-optimism.safe.global/api/v1/safes/xxxxxxxxxxxxxxxxxxxxx/transactions/':

<!doctype html>
<html lang="en">
<head>
  <title>Not Found</title>
</head>
<body>
  <h1>Not Found</h1><p>The requested resource was not found on this server.</p>
</body>
</html>

How can it be fixed?

Need to update the api

Multicall Bytecode is not unique

Environment information

  • ape and plugin versions:
    safe - 0.7.0b0
$ ape --version
# ...copy and paste result of above command here...
0.7.1

$ ape plugins list
# ...copy and paste result of above command here...

Installed Plugins

  alchemy      0.7.1
  etherscan    0.7.0
  foundry      0.7.1
  optimism     0.7.1
  safe         0.7.0b0
  solidity     0.7.1
  • Python Version: 3.9.0
  • OS: osx/linux/win: linux baby!

What went wrong?

The bytecode of the multicall contract 0x998739BFdAAdde7C933B942a68053933098f9EDa is not a unique identifier for the contract, optimism does not match with what is saved under the repo. This results in UnsupportedChainError: Multicall not supported on this chain. when trying to run a multicall on optimism.

Please include information like:

  • what command you ran
        with networks.optimism.mainnet.use_default_provider():
            contract = Contract(address=address,abi=json.loads(abi))
            txn = multisend.MultiSend()
            txn.add(contract.transfer,"0xxxxxxxxxxxxxxxx",1000000,delegatecall=True)
            txn(sender=self.safe)
  • the code that caused the failure (see this link for help with formatting code)
  • full output of the error you received
    UnsupportedChainError: Multicall not supported on this chain.

How can it be fixed?

I would remove the check here in favor of printing an output to the user in case the chain is not endorsed. Endorsed chain ids are already pre-specified here.

Test all Safe versions in public use

Overview

Currently, we just support v1.3.0 in our test suite, we should ensure that our plugin works for v1.4.1, and potentially releases older than v1.3.0 (by first checking for usage of those older versions)

Specification

Add each version as a dependency here:
https://github.com/ApeWorX/ape-safe/blob/main/ape-config.yaml#L13

Then update the new versions here:
https://github.com/ApeWorX/ape-safe/blob/main/tests/conftest.py#L40

Dependencies

May need some Ape core updates for working with multiple versions of the same dependencies

delegate call check broken on optimism

Environment information

  • ape and plugin versions:
    0.7.1

$ ape plugins list

  alchemy      0.7.1
  etherscan    0.7.0
  foundry      0.7.1
  optimism     0.7.1
  safe         0.7.0b0
  solidity     0.7.1
  • Python Version: 3.9.0
  • OS: osx/linux/win linux

What went wrong?

Please include information like:

  • what command you ran
        with networks.optimism.mainnet.use_default_provider():
            contract = Contract(address=address,abi=json.loads(abi))
            txn = multisend.MultiSend()
            txn.add(contract.transfer,"0xxxxxxxxxxxxxxxx",1000000,delegatecall=True)
            txn(sender=self.safe)
  • the code that caused the failure (see this link for help with formatting code)

The error props up in provider.py under the estimate_gas_cost where estimation fails, most likely it's related to txn_params being improperly configured for that gas estimation.

  • full output of the error you received
Traceback (most recent call last):

  File ~/miniconda3/envs/monitor/lib/python3.9/site-packages/ape_ethereum/provider.py:240 in estimate_gas_cost
    return self.web3.eth.estimate_gas(txn_params, block_identifier=block_id)

  File ~/miniconda3/envs/monitor/lib/python3.9/site-packages/web3/eth/eth.py:311 in estimate_gas
    return self._estimate_gas(transaction, block_identifier)

  File ~/miniconda3/envs/monitor/lib/python3.9/site-packages/web3/module.py:75 in caller
    result = w3.manager.request_blocking(

  File ~/miniconda3/envs/monitor/lib/python3.9/site-packages/web3/manager.py:326 in request_blocking
    return self.formatted_response(

  File ~/miniconda3/envs/monitor/lib/python3.9/site-packages/web3/manager.py:287 in formatted_response
    apply_error_formatters(error_formatters, response)

  File ~/miniconda3/envs/monitor/lib/python3.9/site-packages/web3/manager.py:104 in apply_error_formatters
    formatted_resp = pipe(response, error_formatters)

  File cytoolz/functoolz.pyx:680 in cytoolz.functoolz.pipe

  File cytoolz/functoolz.pyx:655 in cytoolz.functoolz.c_pipe

  File ~/miniconda3/envs/monitor/lib/python3.9/site-packages/web3/_utils/contract_error_handling.py:161 in raise_contract_logic_error_on_revert
    raise ContractLogicError(message, data=data)

ContractLogicError: execution reverted: MultiSend should only be called via delegatecall

How can it be fixed?

I changed switched the to in the tx_params variable, to the address of the contract being interacted with in the individual send, rather then the multisend and it seems to have not reverted in the multicall.

tx_params is as follows:

{'chainId': 10, 'to': '0x998739BFdAAdde7C933B942a68053933098f9EDa', 'from': 'MY_SAFE_ADDRESS', 'value': 0, 'data': '0x8d80ff0a00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000079014200000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000242e1a7d4d000000000000000000000000000000000000000000000000000000000000006400000000000000', 'type': '0x02', 'maxFeePerGas': 5373609, 'maxPriorityFeePerGas': 1000000, 'accessList': []}

Fill this in if you have ideas on how the bug could be fixed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.