argent加载模块涉及到钱包合约、模块合约和工厂合约,具体流程如下:
1、walletFactory中创建钱包的时候,会调用baseWallet的init方法绑定模块合约,init方法中会将模块合约地址写入到authorised中并设置值为true;
walletFactory.sol :
_wallet.init(_owner, extendedModules);
...
baseWallet.sol:
function init(address _owner, address[] calldata _modules) external {
require(owner == address(0) && modules == 0, "BW: wallet already initialised");
require(_modules.length > 0, "BW: empty modules");
owner = _owner;
modules = _modules.length;
for (uint256 i = 0; i < _modules.length; i++) {
require(authorised[_modules[i]] == false, "BW: module is already added");
authorised[_modules[i]] = true;
IModule(_modules[i]).init(address(this));
emit AuthorisedModule(_modules[i], true);
}
if (address(this).balance > 0) {
emit Received(address(this).balance, address(0), "");
}
}
2、同时模块合约ArgentModule本身提供了 addModule 方法,来额外的给钱包增加模块,但是该方法只能由钱包主人调用并且必须提前在模块注册合约(ModuleRegistry.sol)进行注册;
//该方法实际是调用的baseWallet合约的authoriseModule方法来设置
function addModule(address _wallet, address _module) external override onlyWalletOwnerOrSelf(_wallet) onlyWhenUnlocked(_wallet) {
require(registry.isRegisteredModule(_module), "AM: module is not registered");
IWallet(_wallet).authoriseModule(_module, true);
}
3、到此为止,模块合约的注册和变更都有说到了,总结如下:
3.1、模块合约的注册在baseWallet合约中;
3.2、如果要调用baseWallet中的invoke方法,必须通过moduleOnly 这个modifier的验证,而这个验证的规则就是只有注册授权的模块才能调用;
4、在梳理argent钱包源码的时候,注册这里也有一些不足和需要优化的地方,例如:
4.1、没有删除模块的功能;
4.2、argentModule由于是继承了relayerManager、tranactionManager 和SecurityManager,所有导致argentModule很大,容易触发eth的合约字节大小限制;
4.3、由于baseWallet合约本身没有实现onERC721Received方法(该方法在tranactionManager中实现),因此在没有加载任何模块的时候,钱包是不支持接受nft资产的;
4.4、由于baseWallet合约本身没有实现addModule方法(该方法在argentModule中实现),因此在没有加载任何模块的时候,钱包是不支持添加模块的,因此必须在创建钱包的时候,将默认的模块添加进去实现基础的功能;
5、下边是梳理的argetModule的继承关系,以及合约内部详细方法: