С этого дня начнем разбирать AA и для начала я решил прочитать серию статей с Alchemy, перевод чего и буду делать тут. Если у вас есть еще какие интересные материалы по этой теме, делитесь в комментариях.
Мне понравилась эта статья тем, что автор разбирает шаги, которые проходило сообщество прежде чем сформировать идею АА, а также множество примеров кода. Далее пойдет уже перевод первой части статьи.
Для начала давайте придумаем, как защитить наши самые ценные активы. Мы хотим иметь возможность подписывать большинство транзакций одним закрытым ключом (как в обычном аккаунте кошельке), и наш бесценный Courage NFT можно будет передать, только если мы подпишем его вторым ключом, который мы закроем в банковском хранилище, охраняемом трехголовым псом.
И вот какой будет наша первая задача.
Каждый счет Ethereum - это либо смарт-контракт, либо счет, принадлежащий внешнему владельцу (EOA), причем последний управляется off-chain с помощью закрытого ключа. Должен ли счет, на котором хранятся эти активы, быть смарт-контрактом или EOA?
На самом деле, держателем активов должен быть смарт-контракт. Если бы это был EOA, то активы всегда можно было бы передать с помощью транзакций, подписанных закрытым ключом EOA, что не обеспечит нужную нам безопасность.
Поэтому, в отличие от большинства людей, наше присутствие onchain будет представлено смарт-контрактом, а не EOA, который мы будем называть кошельком смарт-контракта или просто «кошельком».
Нам нужен способ отдавать команды этому смарт-контракту, чтобы он выполнял нужные нам действия. В частности, нам нужно иметь возможность приказать смарт-контракту выполнить любой вид call()/transfer(), который я мог бы отправить из EOA.
P.S. Каждому пользователю, желающему защитить свои активы таким образом, потребуется собственный смарт-контракт. Не может быть одного большого контракта, в котором хранятся активы нескольких человек, потому что остальная экосистема предполагает, что один адрес представляет одно лицо, и не сможет различать отдельных пользователей.
Например, если кто-то захочет отправить NFT кому-то в контракте с объединенным кошельком, API передачи NFT позволит отправителю указать только адрес объединенного кошелька, но не отдельного пользователя в нем.
Пользовательские операции
Я разверну смарт-контракт кошелька, который будет хранить мои активы и который имеет один метод, в котором я передаю ему информацию о том, какой вызов я хочу, чтобы он сделал.
Назовем данные, представляющие действие, которое я хочу, чтобы кошелек выполнил, пользовательской операцией или user op.
Итак, контракт кошелька выглядит следующим образом:
contract Wallet {
function executeOp(UserOperation op);
}Что входит в пользовательскую операцию?
Во-первых, нам нужны все параметры, которые мы обычно передаем в eth_sendTransaction:
struct UserOperation {
address to;
bytes data;
uint256 value; // Amount of wei sent
uint256 gas;
// ...
}Кроме того, нам нужно предоставить что-то для авторизации запроса - то есть фрагмент данных, на который кошелек будет смотреть, чтобы решить, хочет ли он выполнить операцию или нет.
Для нашего кошелька, защищающего NFT, для большинства пользовательских операций мы передадим подпись остальной части операции, подписанную нашим главным ключом.
Но если пользовательская операция заключается в передаче нашего сверхценного NFT Carbonated Courage, то кошельку потребуется передать подписи остальной части операции, подписанные каждым из двух наших ключей.
Мы также добавим nonce для предотвращения атак повторного воспроизведения, когда кто-то может повторно отправить предыдущую пользовательскую операцию, чтобы запустить ее снова:
struct UserOperation {
// ...
bytes signature;
uint256 nonce;
}Это то, что нам нужно! Пока мой Carbonated Courage NFT находится под действием этого контракта, он не может быть передан без двух подписей.