Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ docs/

# IDE files
.idea/
.vscode/

lcov.info

Expand Down
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ optimizer = true
optimizer_runs = 50
fs_permissions = [{access = "read-write", path = "./"}]

solc_version="0.8.20"
solc_version="0.8.27"

evm_version="shanghai"

Expand Down
44 changes: 44 additions & 0 deletions src/AtomicSigningExecutor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.20;

import "./Matching.sol";
import "./interfaces/IActionVerifier.sol";
import "./interfaces/IAtomicSigner.sol";

// Wrapper contract for the "Executor" role within the Matching contract. Allows for calling out to the singer of an
// action if their signature is "0" before forwarding the request onto Matching itself.

contract AtomicSigningExecutor {
struct AtomicAction {
bool isAtomic;
bytes extraData;
}

Matching public immutable matching;

constructor(Matching _matching) {
matching = _matching;
}

function atomicVerifyAndMatch(
IActionVerifier.Action[] memory actions,
bytes[] memory signatures,
bytes memory actionData,
AtomicAction[] memory atomicActionData
) external onlyTradeExecutor {
for (uint i = 0; i < actions.length; i++) {
AtomicAction memory atomicAction = atomicActionData[i];
if (atomicAction.isAtomic) {
// Call the signer of the action
IAtomicSigner signer = IAtomicSigner(actions[i].signer);
signer.signActionViaPermit(actions[i], atomicAction.extraData, signatures[i]);
}
}
matching.verifyAndMatch(actions, signatures, actionData);
}

modifier onlyTradeExecutor() {
require(matching.tradeExecutors(msg.sender), "AtomicSigningExecutor: Only trade executors can call this function");
_;
}
}
1 change: 1 addition & 0 deletions src/Imports.sol
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

import "openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol";
Expand Down
8 changes: 8 additions & 0 deletions src/interfaces/IAtomicSigner.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.13;

import "./IMatching.sol";

interface IAtomicSigner {
function signActionViaPermit(IMatching.Action memory action, bytes memory extraData, bytes memory signerSig) external;
}
22 changes: 21 additions & 1 deletion src/tokenizedSubaccounts/BaseOnChainSigningTSA.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,35 @@ abstract contract BaseOnChainSigningTSA is BaseTSA {
/////////////

function signActionData(IMatching.Action memory action, bytes memory extraData) external virtual onlySigner {
_signActionData(action, extraData);
}

// TODO: check if we can call this from the backend
function signActionViaPermit(IMatching.Action memory action, bytes memory extraData, bytes memory signerSig)
external
virtual
{
bytes32 hash = getActionTypedDataHash(action);

(address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signerSig);
require(error == ECDSA.RecoverError.NoError && _getBaseSigningTSAStorage().signers[recovered], "Invalid signature");

// require signerSig is a valid signature of signer on hash
_signActionData(action, extraData);
}

function _signActionData(IMatching.Action memory action, bytes memory extraData) internal {
bytes32 hash = getActionTypedDataHash(action);
// TODO: check we want caching. **If params are updated, old ones would not be revoked.**
// if (_getBaseSigningTSAStorage().signedData[hash]) return;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove now?


if (action.signer != address(this)) {
revert BOCST_InvalidAction();
}
_verifyAction(action, hash, extraData);
_getBaseSigningTSAStorage().signedData[hash] = true;

emit ActionSigned(msg.sender, hash, action);
emit ActionSigned(action.signer, hash, action);
}

function revokeActionSignature(IMatching.Action memory action) external virtual onlySigner {
Expand Down
11 changes: 9 additions & 2 deletions src/tokenizedSubaccounts/CollateralManagementTSA.sol
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,14 @@ abstract contract CollateralManagementTSA is BaseOnChainSigningTSA {
depositAssetBalance -= totalPendingDeposits();
}

(int margin, int mtm) = tsaAddresses.manager.getMarginAndMarkToMarket(subAccount(), true, 0);
return _getConvertedMtM() + depositAssetBalance;
}

function _getConvertedMtM() internal view returns (uint) {
BaseTSAAddresses memory tsaAddresses = getBaseTSAAddresses();

// Note: scenario 0 wont calculate full margin for PMRM subaccounts
(int margin, int mtm) = tsaAddresses.manager.getMarginAndMarkToMarket(subAccount(), false, 0);
uint spotPrice = _getBasePrice();

// convert to depositAsset value but in 18dp
Expand All @@ -159,7 +166,7 @@ abstract contract CollateralManagementTSA is BaseOnChainSigningTSA {
revert CMTSA_PositionInsolvent();
}

return uint(convertedMtM) + depositAssetBalance;
return uint(convertedMtM);
}

function _getBasePrice() internal view virtual returns (uint spotPrice);
Expand Down
Loading
Loading