|
46 | 46 | number_of_accounts: 5 |
47 | 47 | ``` |
48 | 48 |
|
| 49 | +You can also change settings at run-time, such as the mnemonic: |
| 50 | +
|
| 51 | +```python |
| 52 | +from ape import accounts |
| 53 | + |
| 54 | +accounts.test_accounts.mnemonic = "candy maple cake sugar pudding cream honey rich smooth crumble sweet treat" |
| 55 | +print(accounts.test_accounts[0]) |
| 56 | +# 0x627306090abaB3A6e1400e9345bC60c78a8BEf57 |
| 57 | +``` |
| 58 | + |
49 | 59 | ```{warning} |
50 | 60 | NEVER put a seed phrase with real funds here. |
51 | 61 | ``` |
@@ -334,6 +344,62 @@ assert recovered_signer == account.address |
334 | 344 | assert account.check_signature(message, signature) |
335 | 345 | ``` |
336 | 346 |
|
| 347 | +### Signing Authorizations (EIP-7702) |
| 348 | + |
| 349 | +If supported by your current ecosystem and account plugins, Ape exposes the capability to set delegate contracts for EOAs via [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) signed `SetCode` Authorizations. |
| 350 | +To sign an Authorization, use `account.sign_authorization` as follows: |
| 351 | + |
| 352 | +```py |
| 353 | +from ape_ethereum import Authorization |
| 354 | +sig = account.sign_authorization(contract) |
| 355 | +auth = Authorization.from_signature( |
| 356 | + address=contract.address, |
| 357 | + chain_id=<chain ID>, |
| 358 | + nonce=account.nonce, |
| 359 | + signature=sig, |
| 360 | +) |
| 361 | +# NOTE: Will execute `methodWithAuth` from `contract` *after* executing authorization |
| 362 | +# NOTE: Make sure to increment the `nonce=` kwarg, as the authorization consumes current nonce |
| 363 | +contract.methodWithAuth(..., authorizations=[auth], sender=account, nonce=account.nonce + 1) |
| 364 | +``` |
| 365 | + |
| 366 | +```{caution} |
| 367 | +Authorizations are **extremely dangerous** and can lead to full account compromise via signature. |
| 368 | +**DO NOT SIGN** an authorization unless you know what you are doing. |
| 369 | +``` |
| 370 | + |
| 371 | +```{note} |
| 372 | +Not all account plugins support signing Authorizations. |
| 373 | +For instance, most hardware wallets may reject signing EIP-7702 Authorizations unless the delegate has been previously whitelisted in their firmware. |
| 374 | +Also, smart contract wallets (such as Safe) cannot sign these message types as only EOAs can sign them. |
| 375 | +``` |
| 376 | + |
| 377 | +Once set, you can see if a delegate contract has been set for your EOA account via `account.delegate`. |
| 378 | +Ape exposes a [convienence subcommand](../commands/accounts.html#accounts-auth) group under `ape accounts` for use in managing your delegations. |
| 379 | + |
| 380 | +Ape also exposes the following convienent higher-level API for working with authorizations in a scripting or testing context: |
| 381 | + |
| 382 | +```py |
| 383 | +assert not account.delegate |
| 384 | + |
| 385 | +# Set `account`'s `.delegate` to `contract` |
| 386 | +account.set_delegate(contract) |
| 387 | +assert account.delegate == contract |
| 388 | + |
| 389 | +# Remove `account`'s `.delegate` |
| 390 | +account.remove_delegate() |
| 391 | +assert not account.delegate |
| 392 | + |
| 393 | +# Temporarily use `contract` as `delegate` (and reset upon exiting context) |
| 394 | +# NOTE: Calls `.set_delegate(contract)` when entering context |
| 395 | +with account.delegate_to(contract) as proxy: |
| 396 | + # NOTE: `proxy` is `Contract(account, contract_type=contract.contract_type)` |
| 397 | + assert contract.contract_type == proxy.contract_type |
| 398 | + proxy.methodWithAuth(..., sender=account) |
| 399 | +# NOTE: calls `remove_delegate()` when exiting context |
| 400 | +assert not account.delegate |
| 401 | +``` |
| 402 | + |
337 | 403 | ## Automation |
338 | 404 |
|
339 | 405 | If you use your keyfile accounts in automation, such as CI/CD, you may need to programmatically unlock them and enable auto-sign. |
|
0 commit comments