Using a Ledger device
This example covers the use of a Ledger device to interact with ZKsync network.
Steps Overview
- Enable blind signing in the Ethereum App.
- Deploy a custom Paymaster contract using
forge create --ledger
. - Fund the paymaster using
cast send --ledger
. - Deploy a
Counter
contract using the paymaster withforge script --ledger
Note that the steps are showcasing different usages of
--ledger
, and not necessarily what are best the best practices for executing a similar flow.
Step-by-Step
Enable blind signing in the Ethereum App
To proceed with the usage of the device, one must first enable “Blind Signing” in the Ethereum App. To do so, open the app on the device, navigate to “Settings”, and then to “Blind signing”. Toggle the option so that it is “Enabled”.
Custom paymaster deployment with forge create
We will be deploying the MyPaymaster
contract introduced in zkUsePaymaster
cheatcode:
forge create ./src/MyPaymaster.sol:MyPaymaster --rpc-url {RPC_URL} --ledger --zksync
Proceed on your device to sign the transaction.
Take note of the resulting deployment address displayed on your terminal, henceforth referred to as $PAYMASTER_ADDRESS
.
Paymaster funding with cast send
To ensure paymaster has sufficient funds to pay for our transactions, we’ll be funding it with some base token:
cast send $PAYMASTER_ADDRESS --value 0.1ether --rpc-url $RPC_URL --ledger
Again, proceed to sign the transaction on your device.
Contract deployment with forge script
We will be deploying a Counter
contract using the paymaster, from within a script using:
vmExt.zkUsePaymaster(vm.envAddress("PAYMASTER_ADDRESS"),
abi.encodeWithSelector(
bytes4(keccak256("general(bytes)")),
bytes("0x")
));
Counter cnt = new Counter();
We can now execute script using forge script --ledger
:
forge script ./scripts/Counter.s.sol --zksync --rpc-url $RPC_URL --broadcast --slow --ledger
In this case, proceed to sign on your device the single broadcastable transaction generated for the deployment. When broadcasting multiple transactions, a proportionate number of signatures is necessary.
Complete code
The following is the full script and source code referenced in this document:
import {Script} from "forge-std/Script.sol";
import {TestExt} from "forge-zksync-std/TestExt.sol";
contract Counter {
uint256 public count = 0;
function increment() public {
count++;
}
function getCount() public view returns (uint256) {
return count;
}
}
contract CounterScript is Script, TestExt {
function setUp() public {}
function run() public {
vm.startBroadcast();
vmExt.zkUsePaymaster(vm.envAddress("PAYMASTER_ADDRESS"),
abi.encodeWithSelector(
bytes4(keccak256("general(bytes)")),
bytes("0x")
));
Counter cnt = new Counter();
vm.stopBroadcast();
}
}