def deploy_compatibility_fallback_handler( cls, ethereum_client: EthereumClient, deployer_account: LocalAccount) -> EthereumTxSent: """ Deploy Compatibility Fallback handler v1.3.0 :param ethereum_client: :param deployer_account: Ethereum account :return: deployed contract address """ contract = get_compatibility_fallback_handler_V1_3_0_contract( ethereum_client.w3) constructor_tx = contract.constructor().buildTransaction() tx_hash = ethereum_client.send_unsigned_transaction( constructor_tx, private_key=deployer_account.key) tx_receipt = ethereum_client.get_transaction_receipt(tx_hash, timeout=60) assert tx_receipt assert tx_receipt["status"] ethereum_tx_sent = EthereumTxSent(tx_hash, constructor_tx, tx_receipt["contractAddress"]) logger.info( "Deployed and initialized Compatibility Fallback Handler version=%s on address %s by %s", "1.3.0", ethereum_tx_sent.contract_address, deployer_account.address, ) return ethereum_tx_sent
def deploy_master_contract( ethereum_client: EthereumClient, deployer_account: LocalAccount) -> EthereumTxSent: """ Deploy master contract. Takes deployer_account (if unlocked in the node) or the deployer private key Safe with version > v1.1.1 doesn't need to be initialized as it already has a constructor :param ethereum_client: :param deployer_account: Ethereum account :return: deployed contract address """ safe_contract = get_safe_contract(ethereum_client.w3) constructor_tx = safe_contract.constructor().buildTransaction() tx_hash = ethereum_client.send_unsigned_transaction( constructor_tx, private_key=deployer_account.key) tx_receipt = ethereum_client.get_transaction_receipt(tx_hash, timeout=60) assert tx_receipt assert tx_receipt['status'] ethereum_tx_sent = EthereumTxSent(tx_hash, constructor_tx, tx_receipt['contractAddress']) logger.info("Deployed and initialized Safe Master Contract=%s by %s", ethereum_tx_sent.contract_address, deployer_account.address) return ethereum_tx_sent
def _deploy_master_contract( ethereum_client: EthereumClient, deployer_account: LocalAccount, contract_fn: Callable[[Web3, Optional[str]], Contract], ) -> EthereumTxSent: """ Deploy master contract. Takes deployer_account (if unlocked in the node) or the deployer private key Safe with version > v1.1.1 doesn't need to be initialized as it already has a constructor :param ethereum_client: :param deployer_account: Ethereum account :param contract_fn: get contract function :return: deployed contract address """ safe_contract = contract_fn(ethereum_client.w3) constructor_tx = safe_contract.constructor().buildTransaction() tx_hash = ethereum_client.send_unsigned_transaction( constructor_tx, private_key=deployer_account.key) tx_receipt = ethereum_client.get_transaction_receipt(tx_hash, timeout=60) assert tx_receipt assert tx_receipt["status"] ethereum_tx_sent = EthereumTxSent(tx_hash, constructor_tx, tx_receipt["contractAddress"]) logger.info( "Deployed and initialized Safe Master Contract version=%s on address %s by %s", contract_fn( ethereum_client.w3, ethereum_tx_sent.contract_address).functions.VERSION().call(), ethereum_tx_sent.contract_address, deployer_account.address, ) return ethereum_tx_sent
def create(ethereum_client: EthereumClient, deployer_account: LocalAccount, master_copy_address: str, owners: List[str], threshold: int, fallback_handler: str = NULL_ADDRESS, proxy_factory_address: Optional[str] = None, payment_token: str = NULL_ADDRESS, payment: int = 0, payment_receiver: str = NULL_ADDRESS) -> EthereumTxSent: """ Deploy new Safe proxy pointing to the specified `master_copy` address and configured with the provided `owners` and `threshold`. By default, payment for the deployer of the tx will be `0`. If `proxy_factory_address` is set deployment will be done using the proxy factory instead of calling the `constructor` of a new `DelegatedProxy` Using `proxy_factory_address` is recommended, as it takes less gas. (Testing with `Ganache` and 1 owner 261534 without proxy vs 229022 with Proxy) """ assert owners, 'At least one owner must be set' assert threshold >= len(owners), 'Threshold=%d must be >= %d' % ( threshold, len(owners)) initializer = get_safe_contract( ethereum_client.w3, NULL_ADDRESS ).functions.setup( owners, threshold, NULL_ADDRESS, # Contract address for optional delegate call b'', # Data payload for optional delegate call fallback_handler, # Handler for fallback calls to this contract, payment_token, payment, payment_receiver).buildTransaction({ 'gas': 1, 'gasPrice': 1 })['data'] if proxy_factory_address: proxy_factory = ProxyFactory(proxy_factory_address, ethereum_client) return proxy_factory.deploy_proxy_contract(deployer_account, master_copy_address, initializer=initializer) proxy_contract = get_delegate_constructor_proxy_contract( ethereum_client.w3) tx = proxy_contract.constructor(master_copy_address, initializer).buildTransaction( {'from': deployer_account.address}) tx['gas'] = tx['gas'] * 100000 tx_hash = ethereum_client.send_unsigned_transaction( tx, private_key=deployer_account.key) tx_receipt = ethereum_client.get_transaction_receipt(tx_hash, timeout=60) assert tx_receipt.status contract_address = tx_receipt.contractAddress return EthereumTxSent(tx_hash, tx, contract_address)