Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forge fmt #29

Merged
merged 4 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ jobs:
forge build --sizes
id: build

- name: Run Forge format
run: |
forge fmt --check
id: format

- name: Run Forge tests
run: |
forge test -vvv
Expand Down
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
5 changes: 2 additions & 3 deletions src/QuarkScript.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ contract QuarkScript {
function owner() internal view returns (address payable) {
address payable owner_;
assembly {
owner_ := sload(0x3bb5ebf00f3b539fbe3d28370e5631dd2bb9520dffcea6daf564f94582db8111) // keccak("org.quark.owner")
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")
relayer_ := sload(0x46ce4d9fc828e2af4f167362c7c43e310c76adc313cd8fe11e785726f972b4f6) // keccak("org.quark.relayer")
}
return relayer_;
}
Expand Down Expand Up @@ -49,4 +49,3 @@ contract QuarkScript {
_;
}
}

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 @@ -68,7 +71,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 @@ -112,9 +117,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 @@ -124,7 +127,9 @@ contract QuarkWallet {
function getActiveCallback() internal returns (address) {
bytes32 slot = ACTIVE_CALLBACK_SLOT;
address callback;
assembly { callback := sload(slot) }
assembly {
callback := sload(slot)
}
return callback;
}

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

/**
Expand All @@ -148,16 +155,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 @@ -195,7 +205,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 @@ -205,7 +219,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 @@ -224,10 +241,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
52 changes: 38 additions & 14 deletions src/Relayer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,26 @@ abstract contract Relayer {
/// @notice The major version of this contract
string public constant version = "0";

/** Internal constants **/
/**
* Internal constants *
*/

/// @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)");

/// @dev The EIP-712 typehash for runTrxScript
bytes32 internal constant TRX_SCRIPT_TYPEHASH = keccak256("TrxScript(address account,uint32 nonce,uint32[] reqs,bytes trxScript,bytes trxCalldata,uint256 expiry)");
bytes32 internal constant TRX_SCRIPT_TYPEHASH = keccak256(
"TrxScript(address account,uint32 nonce,uint32[] reqs,bytes trxScript,bytes trxCalldata,uint256 expiry)"
);

/// @dev See https://ethereum.github.io/yellowpaper/paper.pdf #307)
uint internal constant MAX_VALID_ECDSA_S = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0;
uint256 internal constant MAX_VALID_ECDSA_S = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0;

// Sets a nonce if it's unset, otherwise reverts with `NonceReplay`.
function trySetNonce(address account, uint32 nonce, bool replayable) internal {
uint32 nonceIndex = nonce / 256;
uint32 nonceOffset = nonce - ( nonceIndex * 256 );
uint32 nonceOffset = nonce - (nonceIndex * 256);
uint256 nonceBit = (2 << nonceOffset);

uint256 nonceChunk = nonces[account][uint256(nonceIndex)];
Expand All @@ -62,7 +67,7 @@ abstract contract Relayer {
// TODO: We could make this a lot more efficient if we bulk nonces together
function getNonce(address account, uint32 nonce) internal view returns (bool) {
uint32 nonceIndex = nonce / 256;
uint32 nonceOffset = nonce - ( nonceIndex * 256 );
uint32 nonceOffset = nonce - (nonceIndex * 256);
uint256 nonceBit = (2 << nonceOffset);

uint256 nonceChunk = nonces[account][uint256(nonceIndex)];
Expand Down Expand Up @@ -93,7 +98,17 @@ abstract contract Relayer {
if (uint256(s) > MAX_VALID_ECDSA_S) revert InvalidValueS();
// v ∈ {27, 28} (source: https://ethereum.github.io/yellowpaper/paper.pdf #308)
if (v != 27 && v != 28) revert InvalidValueV();
bytes32 structHash = keccak256(abi.encode(TRX_SCRIPT_TYPEHASH, account, nonce, keccak256(abi.encodePacked(reqs)), keccak256(trxScript), keccak256(trxCalldata), expiry));
bytes32 structHash = keccak256(
abi.encode(
TRX_SCRIPT_TYPEHASH,
account,
nonce,
keccak256(abi.encodePacked(reqs)),
keccak256(trxScript),
keccak256(trxCalldata),
expiry
)
);
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), structHash));
address signatory = ecrecover(digest, v, r, s);
if (signatory == address(0)) revert BadSignatory();
Expand Down Expand Up @@ -132,13 +147,15 @@ abstract contract Relayer {
}

function DOMAIN_SEPARATOR() public view returns (bytes32) {
return keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256("Quark"), keccak256(bytes(version)), block.chainid, address(this)));
return keccak256(
abi.encode(DOMAIN_TYPEHASH, keccak256("Quark"), keccak256(bytes(version)), block.chainid, address(this))
);
}

/**
* @notice Helper function to return a quark address for a given account.
*/
function getQuarkAddress(address account) public virtual view returns (address);
function getQuarkAddress(address account) public view virtual returns (address);

/**
* Run a quark script from a given account. Note: can also use fallback, which is
Expand All @@ -157,7 +174,8 @@ abstract contract Relayer {
return _doRunQuark(msg.sender, quarkCode, quarkCalldata);
}

/***
/**
*
* @notice Runs a given quark script, if valid, from the current sender.
*/
fallback(bytes calldata quarkCode) external payable returns (bytes memory) {
Expand All @@ -166,7 +184,10 @@ abstract contract Relayer {

// Internal function for running a quark. This handles the `create2`, invoking the script,
// and then calling `destruct` to clean it up. We attempt to revert on any failed step.
function _doRunQuark(address account, bytes memory quarkCode, bytes memory quarkCalldata) internal returns (bytes memory) {
function _doRunQuark(address account, bytes memory quarkCode, bytes memory quarkCalldata)
internal
returns (bytes memory)
{
bytes memory resData = _runQuark(account, quarkCode, quarkCalldata);
assembly {
log1(0, 0, 0xDEADBEEF)
Expand All @@ -176,13 +197,16 @@ abstract contract Relayer {

// Internal function for running a quark. This handles the `create2`, invoking the script,
// and then calling `destruct` to clean it up. We attempt to revert on any failed step.
function _runQuark(address account, bytes memory quarkCode, bytes memory quarkCalldata) internal virtual returns (bytes memory);
function _runQuark(address account, bytes memory quarkCode, bytes memory quarkCalldata)
internal
virtual
returns (bytes memory);

/***
/**
*
* @notice Revert given empty call.
*/
receive() external payable {
revert();
}
}

Loading