Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into hans/changes-before-e…
Browse files Browse the repository at this point in the history
…thcall
  • Loading branch information
Hans Wang committed Oct 20, 2023
2 parents 4dcf40c + 22c274b commit ed18a96
Show file tree
Hide file tree
Showing 20 changed files with 271 additions and 267 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: lint

on:
workflow_dispatch:
pull_request:

env:
FOUNDRY_PROFILE: ci

jobs:
check:
strategy:
fail-fast: true

name: Foundry project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Install dependencies
run: forge install

- name: Run Forge build
run: |
forge --version
forge build --sizes
id: build

- name: Run Forge Format
run: |
forge fmt --check
id: format
11 changes: 2 additions & 9 deletions src/CodeJar.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,8 @@ contract CodeJar {
* @return The create2 address based on running the initCode constructor
*/
function getCodeAddress(bytes memory initCode) internal view returns (address) {
return address(uint160(uint(
keccak256(
abi.encodePacked(
bytes1(0xff),
address(this),
uint256(0),
keccak256(initCode)
)
)))
return address(
uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), uint256(0), keccak256(initCode)))))
);
}

Expand Down
16 changes: 16 additions & 0 deletions src/QuarkScript.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@
pragma solidity ^0.8.19;

contract QuarkScript {
function owner() internal view returns (address payable) {
address payable owner_;
assembly {
owner_ := sload(0x3bb5ebf00f3b539fbe3d28370e5631dd2bb9520dffcea6daf564f94582db8111) // keccak("org.quark.owner")
}
return owner_;
}

function relayer() internal view returns (Relayer) {
Relayer relayer_;
assembly {
relayer_ := sload(0x46ce4d9fc828e2af4f167362c7c43e310c76adc313cd8fe11e785726f972b4f6) // keccak("org.quark.relayer")
}
return relayer_;
}

function sloadU256(string memory key) internal view returns (uint256) {
return uint256(sload(key));
}
Expand Down
66 changes: 42 additions & 24 deletions src/QuarkWallet.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import { CodeJar } from "./CodeJar.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {CodeJar} from "./CodeJar.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

contract QuarkWallet {
error BadSignatory();
Expand All @@ -27,10 +27,13 @@ contract QuarkWallet {
bytes32 internal constant ACTIVE_CALLBACK_SLOT = bytes32(keccak256("org.quark.active-callback"));

/// @dev The EIP-712 typehash for authorizing an operation
bytes32 internal constant QUARK_OPERATION_TYPEHASH = keccak256("QuarkOperation(bytes scriptSource,bytes scriptCalldata,uint256 nonce,uint256 expiry,bool allowCallback)");
bytes32 internal constant QUARK_OPERATION_TYPEHASH = keccak256(
"QuarkOperation(bytes scriptSource,bytes scriptCalldata,uint256 nonce,uint256 expiry,bool allowCallback)"
);

/// @dev The EIP-712 typehash for the contract's domain
bytes32 internal constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
bytes32 internal constant DOMAIN_TYPEHASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

/// @notice Name of contract, for use in DOMAIN_SEPARATOR
string public constant name = "Quark Wallet";
Expand All @@ -54,9 +57,9 @@ contract QuarkWallet {
uint256 nonce;
uint256 expiry;
bool allowCallback;
// requirements
// isReplayable
}
// requirements
// isReplayable

constructor(address owner_, CodeJar codeJar_) {
owner = owner_;
Expand All @@ -69,7 +72,9 @@ contract QuarkWallet {
* variable that we are allowed to access with impunity.
*/
bytes32 slot = OWNER_SLOT;
assembly { sstore(slot, owner_) }
assembly {
sstore(slot, owner_)
}
}

/**
Expand Down Expand Up @@ -114,9 +119,7 @@ contract QuarkWallet {
*/
function DOMAIN_SEPARATOR() public view returns (bytes32) {
return keccak256(
abi.encode(
DOMAIN_TYPEHASH, keccak256(bytes(name)), keccak256(bytes(VERSION)), block.chainid, address(this)
)
abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), keccak256(bytes(VERSION)), block.chainid, address(this))
);
}

Expand All @@ -126,7 +129,9 @@ contract QuarkWallet {
function getActiveCallback() internal view returns (address) {
bytes32 slot = ACTIVE_CALLBACK_SLOT;
address callback;
assembly { callback := sload(slot) }
assembly {
callback := sload(slot)
}
return callback;
}

Expand All @@ -138,7 +143,9 @@ contract QuarkWallet {
*/
function setActiveCallback(address callback) internal {
bytes32 slot = ACTIVE_CALLBACK_SLOT;
assembly { sstore(slot, callback) }
assembly {
sstore(slot, callback)
}
}

/**
Expand All @@ -150,16 +157,19 @@ contract QuarkWallet {
* @param s EIP-712 signature s value
* @return return value from the executed operation
*/
function executeQuarkOperation(
QuarkOperation calldata op,
uint8 v,
bytes32 r,
bytes32 s
) public payable returns (bytes memory) {
function executeQuarkOperation(QuarkOperation calldata op, uint8 v, bytes32 r, bytes32 s)
public
payable
returns (bytes memory)
{
if (block.timestamp >= op.expiry) revert SignatureExpired();
if (isSet(op.nonce)) revert InvalidNonce();

bytes32 structHash = keccak256(abi.encode(QUARK_OPERATION_TYPEHASH, op.scriptSource, op.scriptCalldata, op.nonce, op.expiry, op.allowCallback));
bytes32 structHash = keccak256(
abi.encode(
QUARK_OPERATION_TYPEHASH, op.scriptSource, op.scriptCalldata, op.nonce, op.expiry, op.allowCallback
)
);
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), structHash));

if (isValidSignature(owner, digest, v, r, s)) {
Expand Down Expand Up @@ -194,7 +204,11 @@ contract QuarkWallet {
* @param scriptCalldata The encoded function selector and arguments to call on the transaction script
* @return return value from the executed operation
*/
function executeQuarkOperation(bytes calldata scriptSource, bytes calldata scriptCalldata) public payable returns (bytes memory) {
function executeQuarkOperation(bytes calldata scriptSource, bytes calldata scriptCalldata)
public
payable
returns (bytes memory)
{
// XXX authenticate caller
address scriptAddress = codeJar.saveCode(scriptSource);
// XXX add support for allowCallback to the direct path
Expand All @@ -204,7 +218,10 @@ contract QuarkWallet {
/**
* @dev Execute QuarkOperation
*/
function executeQuarkOperationInternal(address scriptAddress, bytes memory scriptCalldata, bool allowCallback) internal returns (bytes memory) {
function executeQuarkOperationInternal(address scriptAddress, bytes memory scriptCalldata, bool allowCallback)
internal
returns (bytes memory)
{
uint256 codeLen;
assembly {
codeLen := extcodesize(scriptAddress)
Expand All @@ -223,10 +240,11 @@ contract QuarkWallet {
}

bool success;
uint returnSize;
uint scriptCalldataLen = scriptCalldata.length;
uint256 returnSize;
uint256 scriptCalldataLen = scriptCalldata.length;
assembly {
success := callcode(gas(), scriptAddress, 0/* value */, add(scriptCalldata, 0x20), scriptCalldataLen, 0x0, 0)
success :=
callcode(gas(), scriptAddress, 0, /* value */ add(scriptCalldata, 0x20), scriptCalldataLen, 0x0, 0)
returnSize := returndatasize()
}

Expand Down
37 changes: 18 additions & 19 deletions src/QuarkWalletFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import "./QuarkWallet.sol";
contract QuarkWalletFactory {
event WalletDeploy(address indexed account, address indexed walletAddress, bytes32 salt);

/// @notice Major version of the contract
uint public constant VERSION = 1;
/// @notice Major version of the contract
uint256 public constant VERSION = 1;

/// @notice Address of CodeJar contract
CodeJar public immutable codeJar;
Expand Down Expand Up @@ -58,21 +58,23 @@ contract QuarkWalletFactory {
* @return address Address of the QuarkWallet for account, salt pair
*/
function walletAddressForAccount(address account, bytes32 salt) public view returns (address) {
return address(uint160(uint(
keccak256(
abi.encodePacked(
bytes1(0xff),
address(this),
salt,
return address(
uint160(
uint256(
keccak256(
abi.encodePacked(
type(QuarkWallet).creationCode,
abi.encode(account),
abi.encode(address(codeJar))
bytes1(0xff),
address(this),
salt,
keccak256(
abi.encodePacked(
type(QuarkWallet).creationCode, abi.encode(account), abi.encode(address(codeJar))
)
)
)
)
)
)))
)
);
}

Expand All @@ -85,13 +87,10 @@ contract QuarkWalletFactory {
* @param s EIP-712 Signature `s` value
* @return bytes Return value of executing the operation
*/
function createAndExecute(
address account,
QuarkWallet.QuarkOperation memory op,
uint8 v,
bytes32 r,
bytes32 s
) external returns (bytes memory) {
function createAndExecute(address account, QuarkWallet.QuarkOperation memory op, uint8 v, bytes32 r, bytes32 s)
external
returns (bytes memory)
{
return createAndExecute(account, 0, op, v, r, s);
}

Expand Down
Loading

0 comments on commit ed18a96

Please sign in to comment.