safe-global / safe-modules Goto Github PK
View Code? Open in Web Editor NEWA collection of modules that can be used with the Safe contract
License: GNU Lesser General Public License v3.0
A collection of modules that can be used with the Safe contract
License: GNU Lesser General Public License v3.0
This issue captures the work for vendoring a PoC ISignatureValidator
implementation that supports WebAuthn.
Specifically, this should verify a WebAuthn signature matches a public key for some input hash.
Note that WebAuthn doesn't allow signing raw hashes, but an "envelope" instead. This needs to be decoded and verified as part of the process.
Existing implementations evaluated in #172 contain
contracts/test
directoryUserOperation
with a WebAuthn signer works over the EntryPoint
Note: all diagrams should be provided using mermaid
@gnosis.pm/safe-contracts/contracts/base/Module.sol is missing on recurring transfer module
Possible approaches:
Evaluate the required Safe 4337 Module contract changes required for the EntryPoint
version 0.7. This should use the “candidate” EntryPoint
version that was submitted for audit.
The expected outcome of this issue is:
When I run yarn inside recurring_transfers
I get the following error (tested on two machines):
yarn
yarn install v1.22.10
[1/4] 🔍 Resolving packages...
warning @gnosis.pm/safe-contracts > @truffle/hdwallet-provider > @trufflesuite/web3-provider-engine > [email protected]: Package renamed: https://www.npmjs.com/package/eth-rpc-errors
warning @gnosis.pm/safe-contracts > @truffle/hdwallet-provider > @trufflesuite/web3-provider-engine > @trufflesuite/eth-json-rpc-middleware > [email protected]: Package renamed: https://www.npmjs.com/package/eth-rpc-errors
warning @gnosis.pm/safe-contracts > @truffle/hdwallet-provider > @trufflesuite/web3-provider-engine > @trufflesuite/eth-json-rpc-infura > [email protected]: Package renamed: https://www.npmjs.com/package/eth-rpc-errors
warning @gnosis.pm/safe-contracts > truffle > mocha > [email protected]: Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)
warning @gnosis.pm/safe-contracts > truffle > mocha > chokidar > [email protected]: "Please update to latest v2.3 or v2.2"
warning @gnosis.pm/safe-contracts > truffle > @truffle/db > pouchdb-adapter-node-websql > websql > sqlite3 > [email protected]: Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future
warning @gnosis.pm/safe-contracts > truffle > @truffle/debugger > reselect-tree > esdoc > ice-cap > cheerio > jsdom > [email protected]: request has been deprecated, see https://github.com/request/request/issues/3142
warning @gnosis.pm/safe-contracts > truffle > @truffle/debugger > web3 > web3-eth > web3-eth-ens > content-hash > [email protected]: stable api reached
warning @gnosis.pm/safe-contracts > truffle > @truffle/debugger > reselect-tree > esdoc > ice-cap > cheerio > jsdom > request > [email protected]: this library is no longer supported
warning solium > [email protected]: Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.
warning solium > chokidar > [email protected]: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning "@gnosis.pm/safe-contracts > truffle > @truffle/db > [email protected]" has unmet peer dependency "abstract-leveldown@*".
warning "@gnosis.pm/safe-contracts > @truffle/hdwallet-provider > @trufflesuite/web3-provider-engine > eth-block-tracker > @babel/[email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".
warning "@gnosis.pm/safe-contracts > truffle > @truffle/db > graphql-tools > @graphql-tools/links > [email protected]" has unmet peer dependency "subscriptions-transport-ws@^0.9.0".
warning "@gnosis.pm/safe-contracts > @truffle/hdwallet-provider > @trufflesuite/web3-provider-engine > eth-block-tracker > @babel/plugin-transform-runtime > [email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".
warning "@gnosis.pm/safe-contracts > @truffle/hdwallet-provider > @trufflesuite/web3-provider-engine > eth-block-tracker > @babel/plugin-transform-runtime > [email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".
warning "@gnosis.pm/safe-contracts > @truffle/hdwallet-provider > @trufflesuite/web3-provider-engine > eth-block-tracker > @babel/plugin-transform-runtime > [email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".
warning "@gnosis.pm/safe-contracts > @truffle/hdwallet-provider > @trufflesuite/web3-provider-engine > eth-block-tracker > @babel/plugin-transform-runtime > babel-plugin-polyfill-corejs2 > @babel/[email protected]" has unmet peer dependency "@babel/core@^7.4.0-0".
warning "@gnosis.pm/safe-contracts > @truffle/hdwallet-provider > @trufflesuite/web3-provider-engine > eth-block-tracker > @babel/plugin-transform-runtime > babel-plugin-polyfill-corejs2 > @babel/helper-define-polyfill-provider > @babel/[email protected]" has unmet peer dependency "@babel/core@^7.0.0".
[4/4] 🔨 Building fresh packages...
[1/22] ⡀ keccak
[15/22] ⡀ websocket
[14/22] ⡀ scrypt
[13/22] ⡀ sqlite3
error /Users/biafra/safe-modules/recurring_transfers/node_modules/sha3: Command failed.
Exit code: 1
Command: node-gyp rebuild
Arguments:
Directory: /Users/biafra/safe-modules/recurring_transfers/node_modules/sha3
Output:
gyp info it worked if it ends with ok
gyp info using [email protected]
gyp info using [email protected] | darwin | x64
gyp info find Python using Python version 2.7.16 found at "/System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python"
gyp info spawn /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
gyp info spawn args [
gyp info spawn args '/usr/local/Cellar/node/15.8.0/libexec/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'make',
gyp info spawn args '-I',
gyp info spawn args '/Users/biafra/safe-modules/recurring_transfers/node_modules/sha3/build/config.gypi',
gyp info spawn args '-I',
gyp info spawn args '/usr/local/Cellar/node/15.8.0/libexec/lib/node_modules/npm/node_modules/node-gyp/addon.gypi',
gyp info spawn args '-I',
gyp info spawn args '/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=/Users/biafra/Library/Caches/node-gyp/15.8.0',
gyp info spawn args '-Dnode_gyp_dir=/usr/local/Cellar/node/15.8.0/libexec/lib/node_modules/npm/node_modules/node-gyp',
gyp info spawn args '-Dnode_lib_file=/Users/biafra/Library/Caches/node-gyp/15.8.0/<(target_arch)/node.lib',
gyp info spawn args '-Dmodule_root_dir=/Users/biafra/safe-modules/recurring_transfers/node_modules/sha3',
gyp info spawn args '-Dnode_engine=v8',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'build',
gyp info spawn args '-Goutput_dir=.'
gyp info spawn args ]
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
CXX(target) Release/obj.target/sha3/src/addon.o
In file included from ../src/addon.cpp:4:
In file included from ../node_modules/nan/nan.h:202:
In file included from ../node_modules/nan/nan_converters.h:67:
../node_modules/nan/nan_converters_43_inl.h:22:1: error: no viable conversion from 'Local<v8::Context>' to 'v8::Isolate *'
X(Boolean)
^~~~~~~~~~
../node_modules/nan/nan_converters_43_inl.h:18:23: note: expanded from macro 'X'
val->To ## TYPE(isolate->GetCurrentContext()) \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:2894:37: note: passing argument to parameter 'isolate' here
Local<Boolean> ToBoolean(Isolate* isolate) const;
^
In file included from ../src/addon.cpp:4:
In file included from ../node_modules/nan/nan.h:202:
In file included from ../node_modules/nan/nan_converters.h:67:
../node_modules/nan/nan_converters_43_inl.h:40:1: error: no viable conversion from 'Local<v8::Context>' to 'v8::Isolate *'
X(bool, Boolean)
^~~~~~~~~~~~~~~~
../node_modules/nan/nan_converters_43_inl.h:37:29: note: expanded from macro 'X'
return val->NAME ## Value(isolate->GetCurrentContext()); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:2904:30: note: passing argument to parameter 'isolate' here
bool BooleanValue(Isolate* isolate) const;
^
In file included from ../src/addon.cpp:4:
In file included from ../node_modules/nan/nan.h:203:
In file included from ../node_modules/nan/nan_new.h:189:
../node_modules/nan/nan_implementation_12_inl.h:103:42: error: no viable conversion from 'v8::Isolate *' to 'Local<v8::Context>'
return scope.Escape(v8::Function::New( isolate
^~~~~~~
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:194:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'v8::Isolate *' to 'const v8::Local<v8::Context> &' for 1st argument
class Local {
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:194:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'v8::Isolate *' to 'v8::Local<v8::Context> &&' for 1st argument
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:198:13: note: candidate template ignored: could not match 'Local<type-parameter-0-0>' against 'v8::Isolate *'
V8_INLINE Local(Local<S> that)
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:4492:22: note: passing argument to parameter 'context' here
Local<Context> context, FunctionCallback callback,
^
In file included from ../src/addon.cpp:4:
In file included from ../node_modules/nan/nan.h:203:
In file included from ../node_modules/nan/nan_new.h:189:
../node_modules/nan/nan_implementation_12_inl.h:337:37: error: too few arguments to function call, expected 2, have 1
return v8::StringObject::New(value).As<v8::StringObject>();
~~~~~~~~~~~~~~~~~~~~~ ^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:5900:3: note: 'New' declared here
static Local<Value> New(Isolate* isolate, Local<String> value);
^
In file included from ../src/addon.cpp:4:
../node_modules/nan/nan.h:1034:53: error: too few arguments to function call, single argument 'context' was not specified
v8::Local<v8::String> string = from->ToString();
~~~~~~~~~~~~~~ ^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:2856:3: note: 'ToString' declared here
V8_WARN_UNUSED_RESULT MaybeLocal<String> ToString(
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8config.h:431:31: note: expanded from macro 'V8_WARN_UNUSED_RESULT'
#define V8_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
^
In file included from ../src/addon.cpp:4:
../node_modules/nan/nan.h:1044:37: error: cannot initialize a parameter of type 'v8::Isolate *' with an lvalue of type 'char *'
length_ = string->WriteUtf8(str_, static_cast<int>(len), 0, flags);
^~~~
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3083:26: note: passing argument to parameter 'isolate' here
int WriteUtf8(Isolate* isolate, char* buffer, int length = -1,
^
In file included from ../src/addon.cpp:4:
../node_modules/nan/nan.h:1818:28: error: no matching member function for call to 'Set'
New(persistentHandle)->Set(New(key).ToLocalChecked(), value);
~~~~~~~~~~~~~~~~~~~~~~~^~~
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3716:37: note: candidate function not viable: requires 3 arguments, but 2 were provided
V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3719:37: note: candidate function not viable: requires 3 arguments, but 2 were provided
V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context, uint32_t index,
^
In file included from ../src/addon.cpp:4:
../node_modules/nan/nan.h:1824:28: error: no matching member function for call to 'Set'
New(persistentHandle)->Set(key, value);
~~~~~~~~~~~~~~~~~~~~~~~^~~
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3716:37: note: candidate function not viable: requires 3 arguments, but 2 were provided
V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3719:37: note: candidate function not viable: requires 3 arguments, but 2 were provided
V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context, uint32_t index,
^
In file included from ../src/addon.cpp:4:
../node_modules/nan/nan.h:1830:28: error: no matching member function for call to 'Set'
New(persistentHandle)->Set(index, value);
~~~~~~~~~~~~~~~~~~~~~~~^~~
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3716:37: note: candidate function not viable: requires 3 arguments, but 2 were provided
V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3719:37: note: candidate function not viable: requires 3 arguments, but 2 were provided
V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context, uint32_t index,
^
In file included from ../src/addon.cpp:4:
../node_modules/nan/nan.h:1836:32: error: no matching member function for call to 'Get'
New(persistentHandle)->Get(New(key).ToLocalChecked()));
~~~~~~~~~~~~~~~~~~~~~~~^~~
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3763:43: note: candidate function not viable: requires 2 arguments, but 1 was provided
V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3766:43: note: candidate function not viable: requires 2 arguments, but 1 was provided
V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
^
In file included from ../src/addon.cpp:4:
../node_modules/nan/nan.h:1842:48: error: no matching member function for call to 'Get'
return scope.Escape(New(persistentHandle)->Get(key));
~~~~~~~~~~~~~~~~~~~~~~~^~~
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3763:43: note: candidate function not viable: requires 2 arguments, but 1 was provided
V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3766:43: note: candidate function not viable: requires 2 arguments, but 1 was provided
V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
^
In file included from ../src/addon.cpp:4:
../node_modules/nan/nan.h:1847:48: error: no matching member function for call to 'Get'
return scope.Escape(New(persistentHandle)->Get(index));
~~~~~~~~~~~~~~~~~~~~~~~^~~
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3763:43: note: candidate function not viable: requires 2 arguments, but 1 was provided
V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:3766:43: note: candidate function not viable: requires 2 arguments, but 1 was provided
V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
^
In file included from ../src/addon.cpp:4:
In file included from ../node_modules/nan/nan.h:2657:
../node_modules/nan/nan_object_wrap.h:24:25: error: no member named 'IsNearDeath' in 'Nan::Persistent<v8::Object, v8::NonCopyablePersistentTraits<v8::Object> >'
assert(persistent().IsNearDeath());
~~~~~~~~~~~~ ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/assert.h:93:25: note: expanded from macro 'assert'
(__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)
^
In file included from ../src/addon.cpp:4:
In file included from ../node_modules/nan/nan.h:2657:
../node_modules/nan/nan_object_wrap.h:67:18: error: no member named 'MarkIndependent' in 'Nan::Persistent<v8::Object, v8::NonCopyablePersistentTraits<v8::Object> >'
persistent().MarkIndependent();
~~~~~~~~~~~~ ^
../node_modules/nan/nan_object_wrap.h:124:26: error: no member named 'IsNearDeath' in 'Nan::Persistent<v8::Object, v8::NonCopyablePersistentTraits<v8::Object> >'
assert(wrap->handle_.IsNearDeath());
~~~~~~~~~~~~~ ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/assert.h:93:25: note: expanded from macro 'assert'
(__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)
^
In file included from ../src/addon.cpp:4:
In file included from ../node_modules/nan/nan.h:2753:
../node_modules/nan/nan_typedarray_contents.h:34:43: warning: 'GetContents' is deprecated: Use GetBackingStore. See http://crbug.com/v8/9908. [-Wdeprecated-declarations]
data = static_cast<char*>(buffer->GetContents().Data()) + byte_offset;
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:5317:3: note: 'GetContents' has been explicitly marked deprecated here
V8_DEPRECATE_SOON("Use GetBackingStore. See http://crbug.com/v8/9908.")
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8config.h:402:39: note: expanded from macro 'V8_DEPRECATE_SOON'
# define V8_DEPRECATE_SOON(message) [[deprecated(message)]]
^
In file included from ../src/addon.cpp:9:
In file included from ../src/KeccakNISTInterface.h:17:
../src/KeccakSponge.h:23:9: warning: 'ALIGN' macro redefined [-Wmacro-redefined]
#define ALIGN __attribute__ ((aligned(32)))
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/i386/param.h:83:9: note: previous definition is here
#define ALIGN(p) __DARWIN_ALIGN(p)
^
../src/addon.cpp:36:64: error: too few arguments to function call, single argument 'context' was not specified
hashlen = info[0]->IsUndefined() ? 512 : info[0]->Int32Value();
~~~~~~~~~~~~~~~~~~~ ^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:2915:3: note: 'Int32Value' declared here
V8_WARN_UNUSED_RESULT Maybe<int32_t> Int32Value(Local<Context> context) const;
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8config.h:431:31: note: expanded from macro 'V8_WARN_UNUSED_RESULT'
#define V8_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
^
../src/addon.cpp:76:36: error: too few arguments to function call, single argument 'context' was not specified
constructor.Reset(t->GetFunction());
~~~~~~~~~~~~~~ ^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:6497:3: note: 'GetFunction' declared here
V8_WARN_UNUSED_RESULT MaybeLocal<Function> GetFunction(
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8config.h:431:31: note: expanded from macro 'V8_WARN_UNUSED_RESULT'
#define V8_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
^
../src/addon.cpp:77:77: error: too few arguments to function call, single argument 'context' was not specified
target->Set(Nan::New<String>("SHA3Hash").ToLocalChecked(), t->GetFunction());
~~~~~~~~~~~~~~ ^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:6497:3: note: 'GetFunction' declared here
V8_WARN_UNUSED_RESULT MaybeLocal<Function> GetFunction(
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8config.h:431:31: note: expanded from macro 'V8_WARN_UNUSED_RESULT'
#define V8_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
^
../src/addon.cpp:97:49: error: too few arguments to function call, single argument 'context' was not specified
Local<Object> buffer_obj = info[0]->ToObject();
~~~~~~~~~~~~~~~~~ ^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8.h:2868:3: note: 'ToObject' declared here
V8_WARN_UNUSED_RESULT MaybeLocal<Object> ToObject(
^
/Users/biafra/Library/Caches/node-gyp/15.8.0/include/node/v8config.h:431:31: note: expanded from macro 'V8_WARN_UNUSED_RESULT'
#define V8_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
^
2 warnings and 19 errors generated.
make: *** [Release/obj.target/sha3/src/addon.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/usr/local/Cellar/node/15.8.0/libexec/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:194:23)
gyp ERR! stack at ChildProcess.emit (node:events:378:20)
gyp ERR! stack at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12)
gyp ERR! System Darwin 19.6.0
gyp ERR! command "/usr/local/Cellar/node/15.8.0/bin/node" "/usr/local/Cellar/node/15.8.0/libexec/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/biafra/safe-modules/recurring_transfers/node_modules/sha3
In its current version, the 4337 module only supporting validating user operations with no validity associated with them (they are valid for all timestamps). There are use cases where user operations should only be valid for a specific time frame, and the 4337 module should be enhanced to support those.
Encode the validUntil
and validAfter
values in the signature bytes.
checkSignatures
to provide multisignature flow (analog to execTransaction
flow`)Technical details:
execTransactionFromModule
execTransactionFromModule
What do I need to do to fix the following error?
yarn test
fails on Linux with the following error:
Error: More than one instance of bitcore-lib found. Please make sure to require bitcore-lib and check that submodules do not also include their own bitcore-lib dependency.
at Object.bitcore.versionGuard (/home/biafra/safe-modules/recurring_transfers/node_modules/bitcore-mnemonic/node_modules/bitcore-lib/index.js:12:11)
at Object.<anonymous> (/home/biafra/safe-modules/recurring_transfers/node_modules/bitcore-mnemonic/node_modules/bitcore-lib/index.js:15:9)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object.<anonymous> (/home/biafra/safe-modules/recurring_transfers/node_modules/bitcore-mnemonic/lib/mnemonic.js:3:15)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object.<anonymous> (/home/biafra/safe-modules/recurring_transfers/node_modules/bitcore-mnemonic/index.js:1:18)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object.<anonymous> (/home/biafra/safe-modules/recurring_transfers/node_modules/eth-lightwallet/lib/keystore.js:8:16)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
Command failed: truffle test
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
$ yarn --version
1.22.10
$ node --version
v10.19.0
From yarn.lock
bitcore-lib@^0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.15.0.tgz#f924be13869f2aab7e04aeec5642ad3359b6cec2"
integrity sha512-AeXLWhiivF6CDFzrABZHT4jJrflyylDWTi32o30rF92HW9msfuKpjzrHtFKYGa9w0kNVv5HABQjCB3OEav4PhQ==
dependencies:
bn.js "=4.11.8"
bs58 "=4.0.1"
buffer-compare "=1.1.1"
elliptic "=6.4.0"
inherits "=2.0.1"
lodash "=4.17.4"
bitcore-lib@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.16.0.tgz#a2c3ec1108cdb90386f728282ab833e0c77c9533"
integrity sha512-CEtcrPAH2gwgaMN+OPMJc18TBEak1+TtzMyafrqrIbK9PIa3kat195qBJhC0liJSHRiRr6IE2eLcXeIFFs+U8w==
dependencies:
bn.js "=4.11.8"
bs58 "=4.0.1"
buffer-compare "=1.1.1"
elliptic "=6.4.0"
inherits "=2.0.1"
lodash "=4.17.11"
bitcore-mnemonic@^1.5.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/bitcore-mnemonic/-/bitcore-mnemonic-1.7.0.tgz#253295a773135e1a0b455871de614996afc8f5e1"
integrity sha512-1JV1okgz9Vv+Y4fG2m3ToR+BGdKA6tSoqjepIxA95BZjW6YaeopVW4iOe/dY9dnkZH4+LA2AJ4YbDE6H3ih3Yw==
dependencies:
bitcore-lib "^0.16.0
unorm "^1.4.1"
[...]
eth-lightwallet@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/eth-lightwallet/-/eth-lightwallet-3.0.1.tgz#297022932aa568f4e4eb0873bff257f5e5b78709"
integrity sha512-79vVCETy+4l1b6wuOWwjqPW3Bom5ZK46BgkUNwaXhiMG1rrMRHjpjYEWMqH0JHeCzOzB4HBIFz7eK1/4s6w5nA==
dependencies:
bitcore-lib "^0.15.0"
bitcore-mnemonic "^1.5.0"
buffer "^4.9.0"
crypto-js "^3.1.5"
elliptic "^3.1.0"
ethereumjs-tx "^1.3.3"
ethereumjs-util "^5.1.1"
rlp "^2.0.0"
scrypt-async "^1.2.0"
tweetnacl "0.13.2"
web3 "0.20.2"
In case of a big vulnerability having a selfdestruct
(only callable by the deployer) would allow us to prevent all users to update their Safes.
Worst case scenario would be that our private key is stolen and the thief calls selfdestruct
. That should never happen and should not be very bad either, users will lose access to the allowance feature. Another one is deployed and the Safes are configured again with the new module address.
Currently, while we have E2E tests that verify that the 4337 module with the Safe contracts work with the reference entry point contract, we do not have the same for the reference bundler implementation.
Implementing this would allow quicker iterations when exploring new features and integrations with 4337.
Migrate the docker-compose.yaml
file from the https://github.com/5afe/playground-4337 repository and create a dedicated E2E test that verifies support.
It should also be possible to extend the setup to additional open source bundlers (such as Alchemy rundler
, Pimlico alto-bundler
).
Contract to be audited:
Just a small cleanup task to rename master
branch to main
, to be in line with our other repositories as well as GitHub defaults.
Safe v1.5.0 has some changes that have an effect on the 4337 module code. Namely:
viaIR
optimization flag to improve gas characteristics of the module (see #207)Implement required changes to the 4337 contracts to ensure compatibility with Safe v1.5.0:
viaIR
flag for improved gas characteristicsDon't update the codebase to account for changes in Safe 1.5.0.
This issue captures the work to make a simple static page that allows signing a ERC-4337 user operation (specifically a SafeOp
) using WebAuthn.
A simple static page that uses the WebAuthn API to:
UserOperation
(note that values can be hardcoded - we only want this for testing purposes!).docker-compose.yaml
file 😄)The same issue as in safe-contracts: safe-global/safe-smart-account#544
If you enabled IR to compile the module, it won't compile because it imports the Safe contracts
The 4337 module currently allows creating a new account (using UserOperation.initCode
) and executing an action atomically.
Furthermore, support for additional signing schemes (such as WebAuthn using P256 curve signatures) is already supported by the Safe by creating a dedicated signer contract per owner (in the case of WebAuthn, one contract per public key) implementing the signature validation logic using ERC-1271.
However, ERC-4337 limits the number of CREATE2
calls to 1 when using initCode
meaning that for example, it is currently not possible to deploy a Safe using account abstraction with nothing but a WebAuthn signer.
The proposed solution would be to split validation into two phases:
validateUserOp
would:
A script similar to An E2E test using the reference bundler where an account can execute a user operation and be deployed as part of the single bundle while using a singleton signer.runOp
where an owner can be deployed with the account as part of the single bundle.
The focus is not to have a useful signer contract, just a process that is supported under 4337.
Right now it's not possible to delete the allowance for one token without removing the whole delegate. In safe-react we have the use case in which we can add or remove a token individually to each delegate.
Possible solution:
deleteAllowance
function to completely disable allowance for 1 tokenThings to check:
This task should be timeboxed, and we can potentially reach out to the Gnosis ecosystem for tips on potential implementations.
More data around potential existing P-256 implementations
The 4337 module currently allows creating a new account (using UserOperation.initCode
) and executing an action atomically.
Furthermore, support for additional signing schemes (such as WebAuthn using P256 curve signatures) is already supported by the Safe by creating a dedicated signer contract per owner (in the case of WebAuthn, one contract per public key) implementing the signature validation logic using ERC-1271.
However, ERC-4337 limits the number of CREATE2
calls to 1 when using initCode
meaning that for example, it is currently not possible to deploy a Safe using account abstraction with nothing but a WebAuthn signer.
Implement a singleton isValidSignature
implementation that can be shared across multiple Safes. You can, for example, deploy sequential new Signer{salt: n}()
for sequential n
to allow multiple owners that use this signing strategy. Each signer would keep a mapping(safe => data)
for each Safe's data required for signature verification.
The downside is that this would still require a staked factory (because the Signer
would access associated storage).
A script similar to runOp
where an owner can be deployed with the account as part of the single bundle.
The focus is not to have a useful signer contract, just a process that is supported under 4337.
Currently, all modules are currently split into separate NPM packages with their own set of dependencies. This ends up causing configuration drift between the modules (Yarn/NPM, linting, etc.) which is not idea.
In order to facilitate code sharing (such as Hardhat tasks, Safe infrastructure deployment code) and development processes (such as linting, formatting), we should convert this monorepo into an NPM workspace.
Currently, the project uses .env
files for configuration, but Hardhat recommends using configuration variables (helps protect against accidentally committing and pushing a .env
file with secrets, and also makes sharing across Hardhat projects seamless - so no need to copy .env
configuration files around).
https://hardhat.org/hardhat-runner/docs/guides/configuration-variables#migrating-from--dotenv
Currently the 4337 local-verify
script will output FAILURE
s for contracts that use immutable
s.
npx hardhat local-verify
Add any other context about the problem here.
This issue is a follow-up to #172.
We should evaluate gas characteristics of existing WebAuthn implementations which may help guide us to choose the optimal WebAuthn library.
As a start, we should setup tests in the 4337 module that can with the FCL WebAuthn signer implementation compute gas usage for both:
#172 already has a rough comparison between different signature verification gas comparisons, so we can extrapolate gas amounts based on the findings in that repository. As a followup, we may choose to vendor additional implementations to compute exact gas amounts.
The allowance module has to be audited after change in #70
Related to #218, but the deployed WebauthnSigner
implementation constructor should support specifying not only the public key, but also the P-256 curve implementation address.
The expected outcome of this issue is a refactored WebauthnSigner
and WebauthnSignerFactory
with an additional P-256 curve implementation parameter. As a bonus, it would be nice to emulate a P-256 signature verification pre-compile in tests to make sure that the WebauthnSigner
and WebauthnSignerFactory
implementations support the pre-compile version as well.
A Safe whose owners are smart contracts and use smart contract signature validation through the ISignatureValidator
interface are not supported by the ERC-4337 module. This is because it always passes the ""
as data bytes to the ISafe.checkSignatures
function.
This would be a huge win for NFT ecosystem and using Safe as a way to securely manage digital collections for big collectors and art institutions.
In order to make the Safe the first audited and formally verified smart contract account that supports the ERC-4337 account standard, we should add Cetora formal verification to the repository's CI.
4337 Gas Metering uses TestEntryPoint
instead of ReferenceEntryPoint
. For accurate gas measurement, using the latter is ideal.
I have a seed phrase in the environment variable MNEMONIC
.
When I try to deploy to Rinkeby via: yarn truffle migrate --network rinkeby --verbose-rpc
Infura does not reply to:
> {
> "jsonrpc": "2.0",
> "id": 1,
> "method": "eth_accounts",
> "params": []
> }
Only when I edit: recurring_transfers/node_modules/@gnosis.pm/util-contracts/src/util/truffleConfig.js
and add my Infura project Id to urlRinkeby
, I can deploy via Infura.
Is that the recommended way?
The current WebauthnSigner
implementation embeds code for verifying P-256 signature in each instance it deploys, which leads to large deployment overhead for passkeys. As such, we should instead deploy a single P-256 curve signature verification contract that can be reused by multiple WebauthnSigner
instances.
The interface should be designed in a way that the Solidity P-256 curve implementation can be easily replaced by the P-256 precompile that is currently proposed as an EIP: https://eips.ethereum.org/EIPS/eip-7212. For example, we can choose to have the shared P-256 signature verifying contract exactly match the pre-compile interface.
We should provide some documentation/ examples how to write a module
Notes:
The allowance module allows for a specified beneficiary to access a specified amount and type of funds stored on a safe contract without requiring additional confirmations from the owners of this safe contract.
The module parameter that can be set are:
It should be possible to revoke an allowance if the required threshold of safe contract owners confirms this change.
The Webauthn signer requires an offset position for challenge, but this can be simplified as the Webauthn standard mandates a specific JSON serialization format.
The expected outcome of this issue is to modify the Webauthn signer’s implementation of computing the signing message to take advantage of the strict JSON serialization format.
Edit: This issue has been replaced by the following 3 sub-tasks:
The idea is that, ultimately, we want to determine how the 4337 module would work for executing a Safe deployment where one of the signers implements an alternative signing scheme (such as WebAuthn, session tokens, etc.). Typically, this requires a separate “signer” contract to also be deployed at the same time as the Safe account in a way that the signature validation logic can be implemented with ERC-1271, but it may also be possible to devise a scheme where this is not necessary by having “singleton” signer implementation contracts (see #148). As such, this issue captured too much research work and was decided to be split into the three issues above.
Original issue contents for reference:
The 4337 module currently allows creating a new account (using UserOperation.initCode
) and executing an action atomically.
Furthermore, support for WebAuthn using P256 curve signatures is already supported by the Safe by creating a dedicated signer contract per user that stores its public key which is used for signature recovery.
However, ERC-4337 limits the number of CREATE2
calls to 1 when using initCode
meaning, it is currently not possible to deploy a Safe using account abstraction with nothing but a WebAuthn signer.
The proposed solution would be to split validation into two phases:
validateUserOp
would:
There may be other alternatives to this flow that can also be researched and suggested. Specifically, a staked factory would allow multiple CREATE2
s, then we should use that approach instead. To evaluate this, potentially reach out to:
A singleton isValidSignature
implementation that can be shared across multiple Safes. You can, for example, deploy sequential new Signer{salt: n}()
for sequential n
to allow multiple owners that use this signing strategy. Each signer would keep a mapping(safe => data)
for each Safe's data required for signature verification.
The downside is that this would still require a staked factory (because the Signer
would access associated storage).
A script similar to runOp
where an owner can be deployed with the account as part of the single bundle.
The focus is not to have a useful signer contract, just a process that is supported under 4337.
Currently, the 4337 package's name is @safe-global/safe-eip4337
. It contains EIP
in the name, which stands for Ethereum Improvement Proposal
. Since 4337 doesn't propose any ethereum protocol-level changes, it is an ERC (Ethereum Request for Comments)
. This is my bad, as I started the project with an incorrect name.
@safe-global/safe-erc4337
@safe-global/safe-erc4337-module
(just throwing it in here; this might be not a good idea, since we also add many related contracts, such as the signer launchpad and passkeys)It turns out that using hardcoded constants instead of keccak256(“…”)
has implications on gas consumption 🤦.
For example changing:
to:
bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;
Has some marginal gas benefits (~13 gas).
Use hardcoded constants.
The EntryPoint is checked in the validation and execution of user operation in 4337 which is done as below:
address entryPoint = _msgSender();
require(entryPoint == SUPPORTED_ENTRYPOINT, "Unsupported entry point");
The above code lines are duplicated in three functions (validateUserOp(...)
, executeUserOp(...)
and executeUserOpWithErrorString(...)
) which can be abstracted away with a modifier
.
Using a modifier which does the same check and integrating it with the above-mentioned functions for better readable code.
The 4337 module currently allows creating a new account (using UserOperation.initCode
) and executing an action atomically.
Furthermore, support for additional signing schemes (such as WebAuthn using P256 curve signatures) is already supported by the Safe by creating a dedicated signer contract per owner (in the case of WebAuthn, one contract per public key) implementing the signature validation logic using ERC-1271.
However, ERC-4337 limits the number of CREATE2
calls to 1 when using initCode
meaning that for example, it is currently not possible to deploy a Safe using account abstraction with nothing but a WebAuthn signer.
It may be the case the ERC-4337 allows a staked factory to execute multiple CREATE2
s, then we should use that approach instead (as it would be the simplest and not require any additional contract work). To evaluate this, potentially reach out to:
A script similar to runOp
where an owner can be deployed with the account as part of the single bundle.
The focus is not to have a useful signer contract, just a process that is supported under 4337.
The setAllowance
function is easy to understand but is not that clear the use case for resetBaseMin
Add an explanation about resetBaseMin
can be used to set allowance reset to be at a desired time of day/week...
I was unable to create a valid Transfer Authorization signature for the Allowance module using ethers' signTypedData
EIP-712 signing function.
Both the signature produced with the EIP-712 schema described in this module's readme as well as an adjusted version (based on the correction of an error I highlighted in this pull request) return:
execution reverted: expectedDelegate == signer && delegates[address(safe)][uint48(signer)].delegate == signer
I was able to find a workaround by producing a hash that, when signed, produces a valid signature. I've attached the code at the bottom of this issue.
Letting end users sign raw hashes is however not good UX- and security-wise, hence my question regarding a way to properly sign with signTypedData (or another EIP-712 method to sign it, I'm not set on using ethers).
This is the code with signTypedData that returns incorrect signatures (I have tried a few variations that also failed):
const domainData = {
chainId: chainId,
verifyingContract: verifyingContract,
}
const message = {
safe: safe,
token: token,
to: to,
amount: ethers.BigNumber.from(amount),
paymentToken: paymentToken,
payment: ethers.BigNumber.from(payment),
nonce: ethers.BigNumber.from(nonce),
}
const types = {
AllowanceTransfer: [
{ name: "safe", type: "address" },
{ name: "token", type: "address" },
{ name: "to", type: "address" },
{ name: "amount", type: "uint96" },
{ name: "paymentToken", type: "address" },
{ name: "payment", type: "uint96" },
{ name: "nonce", type: "uint16" },
],
}
const sig = await signer._signTypedData(domainData, types, message)
let v = parseInt(sig.slice(130, 132), 16)
v += 4
const finalSig = sig.slice(0, 130) + v.toString(16)
return finalSig
This is the code producing the raw hash and valid signatures:
const DOMAIN_SEPARATOR_TYPEHASH = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes(
"EIP712Domain(uint256 chainId,address verifyingContract)"
)
)
const ALLOWANCE_TRANSFER_TYPEHASH = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes(
"AllowanceTransfer(address safe,address token,uint96 amount,address paymentToken,uint96 payment,uint16 nonce)"
)
)
const domainSeparator = ethers.utils.keccak256(
ethers.utils.defaultAbiCoder.encode(
["bytes32", "uint256", "address"],
[DOMAIN_SEPARATOR_TYPEHASH, chainId, verifyingContract]
)
)
const transferHash = ethers.utils.keccak256(
ethers.utils.defaultAbiCoder.encode(
[
"bytes32",
"address",
"address",
"address",
"uint96",
"address",
"uint96",
"uint16",
],
[
ALLOWANCE_TRANSFER_TYPEHASH,
safe,
token,
to,
amount,
paymentToken,
paymentBig,
nonce,
]
)
)
const data = ethers.utils.solidityPack(
["bytes1", "bytes1", "bytes32", "bytes32"],
["0x19", "0x01", domainSeparator, transferHash]
)
const keccak = ethers.utils.keccak256(data)
const finalData = ethers.utils.arrayify(keccak)
const sig = await signer.signMessage(finalData)
let v = parseInt(sig.slice(130, 132), 16)
v += 4
const finalSig = sig.slice(0, 130) + v.toString(16)
return finalSig
I've tried to find any other discussions about this but was unfortunately unsuccessful - any help / pointers would be greatly appreciated. I saw answers on related discussions from you @rmeissner, I hope it's okay to tag you here :)
We should analyse detailed gas metering around the ERC-4337 module compared to the BasicAccount
from the reference ERC-4337 implementation as well as using Gelato for transaction relaying in a few areas:
When analysing ERC-4337 metering, we should check gas metrics with and without account deployment for:
A matrix with gas metering details including:
Original request for context:
Deployment
- Safe without module (meaning using Gelato)
- Safe with 4337 module
- SimpleAccount ethinfinitism
Relaying
- ERC20 transfer using SimpleAccount ethinfinitism
- with Pimlico
- with Alchemy
- Account Deployment
- ERC20 transfer using Safe 4337 module
- with Pimlico
- with Alchemy
- Account Deployment
- ERC20 transfer using Gelato x Safe
Minting
- With Gelato relay and Safe
- With SimpleAccount ethinfinitism and Pimlico
- With safe 4337 module
Existing benchmarking code can exist here: https://github.com/zerodevapp/aa-benchmark
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.