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

Checkout #570

Draft
wants to merge 21 commits into
base: main
Choose a base branch
from
Draft

Checkout #570

wants to merge 21 commits into from

Conversation

kumaryash90
Copy link
Member

No description provided.

@kumaryash90 kumaryash90 marked this pull request as draft November 8, 2023 20:17
Copy link

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

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

Slither found more than 10 potential problems in the proposed changes. Check the Files changed tab for more details.

Copy link

codecov bot commented Nov 8, 2023

Codecov Report

Attention: 57 lines in your changes are missing coverage. Please review.

Comparison is base (2568498) 64.08% compared to head (9d3b113) 63.85%.

Files Patch % Lines
contracts/prebuilts/unaudited/checkout/Vault.sol 30.23% 30 Missing ⚠️
...rebuilts/unaudited/checkout/prb/TargetCheckout.sol 31.42% 24 Missing ⚠️
...ontracts/prebuilts/unaudited/checkout/Executor.sol 80.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #570      +/-   ##
==========================================
- Coverage   64.08%   63.85%   -0.23%     
==========================================
  Files         215      220       +5     
  Lines        6632     6748     +116     
==========================================
+ Hits         4250     4309      +59     
- Misses       2382     2439      +57     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines 23 to 82
contract Checkout is PermissionsEnumerable, ICheckout {
/// @dev Registry of vaults created through this Checkout
mapping(address => bool) public isVaultRegistered;

/// @dev Registry of executors created through this Checkout
mapping(address => bool) public isExecutorRegistered;

address public immutable vaultImplementation;
address public immutable executorImplementation;

constructor(
address _defaultAdmin,
address _vaultImplementation,
address _executorImplementation
) {
vaultImplementation = _vaultImplementation;
executorImplementation = _executorImplementation;

_setupRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);
}

function createVault(address _vaultAdmin, bytes32 _salt) external payable returns (address) {
bytes32 salthash = keccak256(abi.encodePacked(msg.sender, _salt));
address vault = Clones.cloneDeterministic(vaultImplementation, salthash);

(bool success, ) = vault.call(abi.encodeWithSelector(Vault.initialize.selector, _vaultAdmin));

require(success, "Deployment failed");

isVaultRegistered[vault] = true;

emit VaultCreated(vault, _vaultAdmin);

return vault;
}

function createExecutor(address _executorAdmin, bytes32 _salt) external payable returns (address) {
bytes32 salthash = keccak256(abi.encodePacked(msg.sender, _salt));
address executor = Clones.cloneDeterministic(executorImplementation, salthash);

(bool success, ) = executor.call(abi.encodeWithSelector(Executor.initialize.selector, _executorAdmin));

require(success, "Deployment failed");

isExecutorRegistered[executor] = true;

emit ExecutorCreated(executor, _executorAdmin);

return executor;
}

function authorizeVaultToExecutor(address _vault, address _executor) external {
require(IVault(_vault).canAuthorizeVaultToExecutor(msg.sender), "Not authorized");
require(isExecutorRegistered[_executor], "Executor not found");

IVault(_vault).setExecutor(_executor);

emit VaultAuthorizedToExecutor(_vault, _executor);
}
}

Check warning

Code scanning / Slither

Contracts that lock Ether Medium

Contract locking ether found:
Contract Checkout has payable functions:
- ICheckout.createVault(address,bytes32)
- ICheckout.createExecutor(address,bytes32)
- Checkout.createVault(address,bytes32)
- Checkout.createExecutor(address,bytes32)
But does not have a function to withdraw the ether
Comment on lines +37 to +56
function execute(UserOp calldata op) external {
require(_canExecute(), "Not authorized");

if (op.valueToSend != 0) {
IVault(op.vault).transferTokensToExecutor(op.currency, op.valueToSend);
}

bool success;
if (op.currency == CurrencyTransferLib.NATIVE_TOKEN) {
(success, ) = op.target.call{ value: op.valueToSend }(op.data);
} else {
if (op.approvalRequired) {
IERC20(op.currency).approve(op.target, op.valueToSend);
}

(success, ) = op.target.call(op.data);
}

require(success, "Execution failed");
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines +59 to +72
function createExecutor(address _executorAdmin, bytes32 _salt) external payable returns (address) {
bytes32 salthash = keccak256(abi.encodePacked(msg.sender, _salt));
address executor = Clones.cloneDeterministic(executorImplementation, salthash);

(bool success, ) = executor.call(abi.encodeWithSelector(Executor.initialize.selector, _executorAdmin));

require(success, "Deployment failed");

isExecutorRegistered[executor] = true;

emit ExecutorCreated(executor, _executorAdmin);

return executor;
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities Low

Comment on lines +44 to +57
function createVault(address _vaultAdmin, bytes32 _salt) external payable returns (address) {
bytes32 salthash = keccak256(abi.encodePacked(msg.sender, _salt));
address vault = Clones.cloneDeterministic(vaultImplementation, salthash);

(bool success, ) = vault.call(abi.encodeWithSelector(Vault.initialize.selector, _vaultAdmin));

require(success, "Deployment failed");

isVaultRegistered[vault] = true;

emit VaultCreated(vault, _vaultAdmin);

return vault;
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities Low

Comment on lines +43 to +49
function withdraw(address _token, uint256 _amount) external {
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Not authorized");

CurrencyTransferLib.transferCurrency(_token, address(this), msg.sender, _amount);

emit TokensWithdrawn(_token, _amount);
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities Low

Comment on lines +96 to +119
function _swap(SwapOp memory _swapOp) internal {
address _tokenIn = _swapOp.tokenIn;
address _router = _swapOp.router;

// get quote for amountIn
(, bytes memory quoteData) = _router.staticcall(_swapOp.quoteCalldata);
uint256 amountIn;
uint256 offset = _swapOp.amountInOffset;

assembly {
amountIn := mload(add(add(quoteData, 32), offset))
}

// perform swap
bool success;
if (_tokenIn == CurrencyTransferLib.NATIVE_TOKEN) {
(success, ) = _router.call{ value: amountIn }(_swapOp.swapCalldata);
} else {
IERC20(_tokenIn).approve(_swapOp.router, amountIn);
(success, ) = _router.call(_swapOp.swapCalldata);
}

require(success, "Swap failed");
}

Check failure

Code scanning / Slither

Functions that send Ether to arbitrary destinations High

Comment on lines +96 to +119
function _swap(SwapOp memory _swapOp) internal {
address _tokenIn = _swapOp.tokenIn;
address _router = _swapOp.router;

// get quote for amountIn
(, bytes memory quoteData) = _router.staticcall(_swapOp.quoteCalldata);
uint256 amountIn;
uint256 offset = _swapOp.amountInOffset;

assembly {
amountIn := mload(add(add(quoteData, 32), offset))
}

// perform swap
bool success;
if (_tokenIn == CurrencyTransferLib.NATIVE_TOKEN) {
(success, ) = _router.call{ value: amountIn }(_swapOp.swapCalldata);
} else {
IERC20(_tokenIn).approve(_swapOp.router, amountIn);
(success, ) = _router.call(_swapOp.swapCalldata);
}

require(success, "Swap failed");
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines +69 to +84
function swapAndTransferTokensToExecutor(address _token, uint256 _amount, SwapOp memory _swapOp) external {
require(_canTransferTokens(), "Not authorized");
require(isApprovedRouter[_swapOp.router], "Invalid router address");

_swap(_swapOp);

uint256 balance = _token == CurrencyTransferLib.NATIVE_TOKEN
? address(this).balance
: IERC20(_token).balanceOf(address(this));

require(balance >= _amount, "Not enough balance");

CurrencyTransferLib.transferCurrency(_token, address(this), msg.sender, _amount);

emit TokensTransferredToExecutor(msg.sender, _token, _amount);
}
Comment on lines +96 to +119
function _swap(SwapOp memory _swapOp) internal {
address _tokenIn = _swapOp.tokenIn;
address _router = _swapOp.router;

// get quote for amountIn
(, bytes memory quoteData) = _router.staticcall(_swapOp.quoteCalldata);
uint256 amountIn;
uint256 offset = _swapOp.amountInOffset;

assembly {
amountIn := mload(add(add(quoteData, 32), offset))
}

// perform swap
bool success;
if (_tokenIn == CurrencyTransferLib.NATIVE_TOKEN) {
(success, ) = _router.call{ value: amountIn }(_swapOp.swapCalldata);
} else {
IERC20(_tokenIn).approve(_swapOp.router, amountIn);
(success, ) = _router.call(_swapOp.swapCalldata);
}

require(success, "Swap failed");
}

Check warning

Code scanning / Slither

Assembly usage Warning

Comment on lines +96 to +119
function _swap(SwapOp memory _swapOp) internal {
address _tokenIn = _swapOp.tokenIn;
address _router = _swapOp.router;

// get quote for amountIn
(, bytes memory quoteData) = _router.staticcall(_swapOp.quoteCalldata);
uint256 amountIn;
uint256 offset = _swapOp.amountInOffset;

assembly {
amountIn := mload(add(add(quoteData, 32), offset))
}

// perform swap
bool success;
if (_tokenIn == CurrencyTransferLib.NATIVE_TOKEN) {
(success, ) = _router.call{ value: amountIn }(_swapOp.swapCalldata);
} else {
IERC20(_tokenIn).approve(_swapOp.router, amountIn);
(success, ) = _router.call(_swapOp.swapCalldata);
}

require(success, "Swap failed");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant