I am unable to compile ZkMinimalAccount.sol
when doing forge build --zksync
#2952
Answered
by
shashankTwr
shashankTwr
asked this question in
Q&A
-
below is my // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// zksync era imports
import {
IAccount,
ACCOUNT_VALIDATION_SUCCESS_MAGIC
} from "lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol";
import {
Transaction,
MemoryTransactionHelper,
EIP_712_TX_TYPE
} from "lib/foundry-era-contracts/src/system-contracts/contracts//libraries/MemoryTransactionHelper.sol";
import {SystemContractsCaller} from
"lib/foundry-era-contracts/src/system-contracts/contracts/libraries/SystemContractsCaller.sol";
import {
NONCE_HOLDER_SYSTEM_CONTRACT,
BOOTLOADER_FORMAL_ADDRESS,
DEPLOYER_SYSTEM_CONTRACT
} from "lib/foundry-era-contracts/src/system-contracts/contracts/Constants.sol";
import {INonceHolder} from "lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/INonceHolder.sol";
import {Utils} from "lib/foundry-era-contracts/src/system-contracts/contracts/libraries/Utils.sol";
//0z imports
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
/*
* Lifecycle of a type 113(0x71) transaction
* msg.sender is the bootloader system contract
* Phase 1 Validation
* 1. The user sends the transaction to the "zkSync API client"(sort of a "light node")
* 2. The zkSync API client checks to see the nonce is unique by querying the NonceHolder system contract
* 3. The zkSync API client calls the `validateTransaction` which must update Nonce
* 4. The zkSync API client checks the nonce is updated
* 5. The zkSync API client calls payForTransaction or PrepareForPaymaster & validateAndPayForPlayMasterTransaction
* 6. the zkSync API client verifies that bootloader gets paid
*
*
*
* Phase 2 Execution
* 7. the zkSync API client passes the validated transaction to the main node/ sequencer (both are same currently)
* 8. main node will call the executeTransaction
* 9. If a paymaster is used postTransaction is called
*/
contract ZkMinimalAccount is IAccount, Ownable {
using MemoryTransactionHelper for Transaction;
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error ZkMinimalAccount__NotEnoughBalance();
error ZkMinimalAccount__NotFromBootLoader();
error ZkMinimalAccount__ExecutionFailed();
error ZkMinimalAccount__NeitherFromBootLoaderNorOwner();
error ZkMinimalAccount__FailedToPay();
error ZkMinimalAccount__ValidationFailed();
/*//////////////////////////////////////////////////////////////
MODIFIER
//////////////////////////////////////////////////////////////*/
modifier requireFromBootLoader() {
if (msg.sender != BOOTLOADER_FORMAL_ADDRESS) {
revert ZkMinimalAccount__NotFromBootLoader();
}
_;
}
modifier requireFromBootLoaderOrOwner() {
if (msg.sender != BOOTLOADER_FORMAL_ADDRESS && msg.sender != owner()) {
revert ZkMinimalAccount__NeitherFromBootLoaderNorOwner();
}
_;
}
/*//////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////*/
constructor() Ownable(msg.sender) {}
receive() external payable {}
/*//////////////////////////////////////////////////////////////
EXTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
/*
/// @notice Must increase the nonce
/// @notice Must validate the transaction (check the owner signed the transaction)
/// @param _txHash
/// @param _suggestedSignedHash )
/// @param _transaction Structure used to represent a zkSync transaction.
/// @return magic The magic value that should be equal to the signature of this function
/// if the user agrees to proceed with the transaction
*/
function validateTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction)
external
payable
requireFromBootLoader
returns (bytes4 magic)
{
return _validateTransaction(_transaction);
}
function executeTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction)
external
payable
{
_executeTransaction(_transaction);
}
// you signed a tx
// send a signed tx to your friend
// they can send it by calling this function
// There is no point in providing possible signed hash in the `executeTransactionFromOutside` method,
// since it typically should not be trusted.
function executeTransactionFromOutside(Transaction calldata _transaction) external payable {
bytes4 magic = _validateTransaction(_transaction);
if (magic != bytes4(0)) {
revert ZkMinimalAccount__ValidationFailed();
}
_executeTransaction(_transaction);
}
function payForTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction)
external
payable
{
bool success = _transaction.payToTheBootloader();
if (!success) {
revert ZkMinimalAccount__FailedToPay();
}
_executeTransaction(_transaction);
}
// Called when u are a paymaster
function prepareForPaymaster(bytes32 _txHash, bytes32 _possibleSignedHash, Transaction calldata _transaction)
external
payable
{}
/*//////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
function _validateTransaction(Transaction calldata _transaction) internal view returns (bytes4 magic) {
// Call nonceholder
// increment nonce
// call(x,y,z) -> system contract call
SystemContractsCaller.systemCallWithPropagatedRevert(
uint32(gasleft()),
address(NONCE_HOLDER_SYSTEM_CONTRACT),
0,
abi.encodeCall(INonceHolder.incrementMinNonceIfEquals, (_transaction.nonce))
);
// check for fee to pay
uint256 totalRequiredBalance = _transaction.totalRequiredBalance();
if (totalRequiredBalance > address(this).balance) {
revert ZkMinimalAccount__NotEnoughBalance();
}
// check the signature
bytes32 txHash = _transaction.encodeHash();
bytes32 convertedHash = MessageHashUtils.toEthSignedMessageHash(txHash);
address signer = ECDSA.recover(convertedHash, _transaction.signature);
bool isValidSignature = signer == owner();
// return the "magic" number
if (isValidSignature) {
magic = ACCOUNT_VALIDATION_SUCCESS_MAGIC;
} else {
magic = bytes4(0);
}
return magic;
}
function _executeTransaction(Transaction calldata _transaction) internal requireFromBootLoaderOrOwner {
address to = address(uint160(_transaction.to)); //uint256 to add
uint128 value = Utils.safeCastToU128(_transaction.value);
bytes memory data = _transaction.data;
if (to == address(DEPLOYER_SYSTEM_CONTRACT)) {
uint32 gas = Utils.safeCastToU32(gasleft());
SystemContractsCaller.systemCallWithPropagatedRevert(gas, to, value, data);
} else {
bool success;
assembly {
success := call(gas(), to, value, add(data, 0x20), mload(data), 0, 0)
}
if (!success) {
revert ZkMinimalAccount__ExecutionFailed();
}
}
}
} when i run the [⠃] Using zksolc-1.5.7
[⠊] Compiling (zksync)
[⠃] Compiling 84 files with zksolc and ZKsync solc 0.8.27
[⠊] zksolc and ZKsync solc 0.8.27 finished in 768.22ms
Error: Compiler run failed:
Error (3656)
TypeError: Contract "ZkMinimalAccount" should be marked as abstract.
--> src/zksync/ZkMinimalAccount.sol:49:1:
|
49 | contract ZkMinimalAccount is IAccount, Ownable {
| ^ (Relevant source part starts here and spans across multiple lines).
Note: Missing implementation:
--> lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol:25:5:
|
25 | function executeTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction)
| ^ (Relevant source part starts here and spans across multiple lines).
Note: Missing implementation:
--> lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol:31:5:
|
31 | function executeTransactionFromOutside(Transaction calldata _transaction) external payable;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Missing implementation:
--> lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol:33:5:
|
33 | function payForTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction)
| ^ (Relevant source part starts here and spans across multiple lines).
Note: Missing implementation:
--> lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol:37:5:
|
37 | function prepareForPaymaster(bytes32 _txHash, bytes32 _possibleSignedHash, Transaction calldata _transaction)
| ^ (Relevant source part starts here and spans across multiple lines).
Note: Missing implementation:
--> lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol:20:5:
|
20 | function validateTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction)
| ^ (Relevant source part starts here and spans across multiple lines).
Error (9914)
TypeError: Function overload clash during conversion to external types for arguments.
--> lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol:25:5:
|
25 | function executeTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction)
| ^ (Relevant source part starts here and spans across multiple lines).
Error (9914)
TypeError: Function overload clash during conversion to external types for arguments.
--> lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol:31:5:
|
31 | function executeTransactionFromOutside(Transaction calldata _transaction) external payable;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error (9914)
TypeError: Function overload clash during conversion to external types for arguments.
--> lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol:33:5:
|
33 | function payForTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction)
| ^ (Relevant source part starts here and spans across multiple lines).
Error (9914)
TypeError: Function overload clash during conversion to external types for arguments.
--> lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol:37:5:
|
37 | function prepareForPaymaster(bytes32 _txHash, bytes32 _possibleSignedHash, Transaction calldata _transaction)
| ^ (Relevant source part starts here and spans across multiple lines).
Error (9914)
TypeError: Function overload clash during conversion to external types for arguments.
--> lib/foundry-era-contracts/src/system-contracts/contracts/interfaces/IAccount.sol:20:5:
|
20 | function validateTransaction(bytes32 _txHash, bytes32 _suggestedSignedHash, Transaction calldata _transaction)
| ^ (Relevant source part starts here and spans across multiple lines). Error was same with
|
Beta Was this translation helpful? Give feedback.
Answered by
shashankTwr
Nov 30, 2024
Replies: 1 comment 2 replies
-
It appear to me that you haven't correctly implemented your |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I figured out the issue, there's an extra forward slash in the import, code is compiling properly now.
Thanks a lot for the response @EngrPips